[libmnetutil] Initial commit (see review request in rhbz #626458)

Peter Lemenkov peter at fedoraproject.org
Mon Oct 11 09:36:00 UTC 2010


commit 86547b935411e9ce3c5d6df5d3257ccc1710ed21
Author: Peter Lemenkov <lemenkov at gmail.com>
Date:   Mon Oct 11 13:36:03 2010 +0400

    Initial commit (see review request in rhbz #626458)
    
    Signed-off-by: Peter Lemenkov <lemenkov at gmail.com>

 .gitignore                                 |    1 +
 libmnetutil-0001-Remove-bundled-udns.patch | 7987 ++++++++++++++++++++++++++++
 libmnetutil.spec                           |   79 +
 sources                                    |    1 +
 4 files changed, 8068 insertions(+), 0 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index e69de29..463d122 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/libmnetutil-0.8.0.tar.bz2
diff --git a/libmnetutil-0001-Remove-bundled-udns.patch b/libmnetutil-0001-Remove-bundled-udns.patch
new file mode 100644
index 0000000..1c05949
--- /dev/null
+++ b/libmnetutil-0001-Remove-bundled-udns.patch
@@ -0,0 +1,7987 @@
+From 004d6bfdc51ddcacec616bed945904b0e3965e10 Mon Sep 17 00:00:00 2001
+From: Peter Lemenkov <lemenkov at gmail.com>
+Date: Mon, 23 Aug 2010 19:20:39 +0400
+Subject: [PATCH] Remove bundled udns
+
+Signed-off-by: Peter Lemenkov <lemenkov at gmail.com>
+---
+ Makefile.am                  |    6 +-
+ configure.ac                 |    1 -
+ source/init.cxx              |    2 +-
+ udns/Makefile.am             |   84 ---
+ udns/source/.cvsignore       |    9 -
+ udns/source/COPYING.LGPL     |  504 ----------------
+ udns/source/Makefile         |  132 -----
+ udns/source/NEWS             |   53 --
+ udns/source/NOTES            |  193 ------
+ udns/source/TODO             |   74 ---
+ udns/source/debian/changelog |   94 ---
+ udns/source/debian/control   |   33 -
+ udns/source/debian/copyright |   24 -
+ udns/source/debian/rules     |   91 ---
+ udns/source/dnsget.1         |  182 ------
+ udns/source/dnsget.c         |  709 ----------------------
+ udns/source/ex-rdns.c        |  111 ----
+ udns/source/rblcheck.1       |  151 -----
+ udns/source/rblcheck.c       |  364 ------------
+ udns/source/udns.3           | 1284 ----------------------------------------
+ udns/source/udns.h           |  736 -----------------------
+ udns/source/udns_bl.c        |  160 -----
+ udns/source/udns_dn.c        |  382 ------------
+ udns/source/udns_dntosp.c    |   30 -
+ udns/source/udns_misc.c      |   67 ---
+ udns/source/udns_parse.c     |  169 ------
+ udns/source/udns_resolver.c  | 1342 ------------------------------------------
+ udns/source/udns_rr_a.c      |  124 ----
+ udns/source/udns_rr_mx.c     |   91 ---
+ udns/source/udns_rr_naptr.c  |  128 ----
+ udns/source/udns_rr_ptr.c    |  109 ----
+ udns/source/udns_rr_srv.c    |  154 -----
+ udns/source/udns_rr_txt.c    |   98 ---
+ 33 files changed, 4 insertions(+), 7687 deletions(-)
+ delete mode 100644 udns/Makefile.am
+ delete mode 100644 udns/source/.cvsignore
+ delete mode 100644 udns/source/COPYING.LGPL
+ delete mode 100755 udns/source/Makefile
+ delete mode 100644 udns/source/NEWS
+ delete mode 100644 udns/source/NOTES
+ delete mode 100644 udns/source/TODO
+ delete mode 100644 udns/source/debian/changelog
+ delete mode 100644 udns/source/debian/control
+ delete mode 100644 udns/source/debian/copyright
+ delete mode 100755 udns/source/debian/rules
+ delete mode 100644 udns/source/dnsget.1
+ delete mode 100644 udns/source/dnsget.c
+ delete mode 100644 udns/source/ex-rdns.c
+ delete mode 100644 udns/source/rblcheck.1
+ delete mode 100644 udns/source/rblcheck.c
+ delete mode 100644 udns/source/udns.3
+ delete mode 100644 udns/source/udns.h
+ delete mode 100644 udns/source/udns_bl.c
+ delete mode 100644 udns/source/udns_dn.c
+ delete mode 100644 udns/source/udns_dntosp.c
+ delete mode 100644 udns/source/udns_misc.c
+ delete mode 100644 udns/source/udns_parse.c
+ delete mode 100644 udns/source/udns_resolver.c
+ delete mode 100644 udns/source/udns_rr_a.c
+ delete mode 100644 udns/source/udns_rr_mx.c
+ delete mode 100644 udns/source/udns_rr_naptr.c
+ delete mode 100644 udns/source/udns_rr_ptr.c
+ delete mode 100644 udns/source/udns_rr_srv.c
+ delete mode 100644 udns/source/udns_rr_txt.c
+
+diff --git a/Makefile.am b/Makefile.am
+index c0fb0a3..dd529d9 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,17 +1,17 @@
+ pkgconfigdir = $(libdir)/pkgconfig
+ 
+-SUBDIRS = udns win32 . examples include m4 tests debian
++SUBDIRS = win32 . examples include m4 tests debian
+ DIST_SUBDIRS = $(SUBDIRS)
+ EXTRA_DIST = libmnetutil.spec
+ 
+-AM_CPPFLAGS = $(MINISIP_CFLAGS) -I$(srcdir)/include -I$(srcdir)/udns/source
++AM_CPPFLAGS = $(MINISIP_CFLAGS) -I$(srcdir)/include
+ 
+ pkgconfig_DATA = libmnetutil.pc
+ 
+ lib_LTLIBRARIES = libmnetutil.la
+ # libmnetutil_la_CPPFLAGS = 
+ libmnetutil_la_LDFLAGS = $(MINISIP_LIBRARY_LDFLAGS)
+-libmnetutil_la_LIBADD = udns/libudns.la  $(LTLIBOBJS) $(MINISIP_LIBS) $(LDAP_LIBS)
++libmnetutil_la_LIBADD = -ludns  $(LTLIBOBJS) $(MINISIP_LIBS) $(LDAP_LIBS)
+ libmnetutil_la_DEPENDENCIES = $(LTLIBOBJS)
+ 
+ libmnetutil_la_SOURCES = $(mnetutil_src)
+diff --git a/configure.ac b/configure.ac
+index fae7740..4a54aac 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -105,7 +105,6 @@ AC_CONFIG_FILES([
+ 		include/Makefile 
+ 		m4/Makefile 
+ 		tests/Makefile
+-		udns/Makefile
+ 		debian/Makefile
+ 		win32/Makefile 
+ 		win32/libmnetutil-res.rc
+diff --git a/source/init.cxx b/source/init.cxx
+index ca5d9b4..79fe030 100644
+--- a/source/init.cxx
++++ b/source/init.cxx
+@@ -34,7 +34,7 @@ LIBMNETUTIL_API void libmnetutilInit()
+ 	if( g_initialized++ > 0 )
+ 		return;
+ 
+-	if( dns_init(0) < 0 ) {
++	if( dns_init(0, 0) < 0 ) {
+ 		g_initialized--;
+ 		throw Exception( "libmnetutil udns initialization failed" );
+ 	}
+diff --git a/udns/Makefile.am b/udns/Makefile.am
+deleted file mode 100644
+index bada1f2..0000000
+--- a/udns/Makefile.am
++++ /dev/null
+@@ -1,84 +0,0 @@
+-#! /usr/bin/make -rf
+-# $Id: Makefile,v 1.38 2005/09/12 12:09:10 mjt Exp $
+-# libudns Makefile
+-#
+-# Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-# Copyright (C) 2006  Mikael Magnusson <mikma at users.sourceforge.net>
+-# This file is part of UDNS library, an async DNS stub resolver.
+-#
+-# This library is free software; you can redistribute it and/or
+-# modify it under the terms of the GNU Lesser General Public
+-# License as published by the Free Software Foundation; either
+-# version 2.1 of the License, or (at your option) any later version.
+-#
+-# This library 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
+-# Lesser General Public License for more details.
+-#
+-# You should have received a copy of the GNU Lesser General Public
+-# License along with this library, in file named COPYING.LGPL; if not,
+-# write to the Free Software Foundation, Inc., 59 Temple Place,
+-# Suite 330, Boston, MA  02111-1307  USA
+-
+-noinst_LTLIBRARIES = \
+-		libudns.la
+-
+-AM_CPPFLAGS = $(MINISIP_CFLAGS) -D_WIN32_WINNT=0x501 -DHANDLE_ERROR=NULL -DEOVERFLOW=-1 -I$(srcdir)/source -DNO_INET6 
+-AM_LDFLAGS = $(MINISIP_LIBRARY_LDFLAGS)
+-
+-VERS   = 0.0.8
+-
+-SRCS = source/udns_dn.c				\
+-	source/udns_dntosp.c			\
+-	source/udns_parse.c			\
+-	source/udns_resolver.c			\
+-	source/udns_misc.c			\
+-	source/udns_rr_a.c			\
+-	source/udns_rr_ptr.c			\
+-	source/udns_rr_mx.c			\
+-	source/udns_rr_txt.c			\
+-	source/udns_bl.c			\
+-	source/udns_rr_srv.c			\
+-	source/udns_rr_naptr.c			\
+-	source/udns.h				\
+-	udns_codes.c
+-USRCS  = dnsget.c rblcheck.c ex-rdns.c
+-DIST   = COPYING.LGPL udns.h udns.3 dnsget.1 rblcheck.1 $(USRCS) \
+-	Makefile TODO
+-
+-libudns_la_SOURCES = $(SRCS)
+-
+-libudns_la_LIBADD = $(MINISIP_LIBS)
+-
+-#EXTRADIST = $(addprefix source/,$(DIST))
+-CLEANFILES = udns_codes.c
+-
+-
+-# udns_codes.c is generated from udns.h
+-udns_codes.c:	source/udns.h Makefile
+-	@echo Generating $@
+-	@set -e; exec >$@.tmp; \
+-	set T type C class R rcode; \
+-	echo "/* Automatically generated. */"; \
+-	echo "#include \"udns.h\""; \
+-	while [ "$$1" ]; do \
+-	 echo; \
+-	 echo "const struct dns_nameval dns_$${2}tab[] = {"; \
+-	 $(AWK) "/^  DNS_$${1}_[A-Z0-9_]+[ 	]*=/ \
+-	  { printf \" {%s,\\\"%s\\\"},\\n\", \$$1, substr(\$$1,7) }" \
+-	  $(srcdir)/source/udns.h ; \
+-	 echo " {0,0}};"; \
+-	 echo "const char *dns_$${2}name(enum dns_$${2} code) {"; \
+-	 echo " static char nm[20];"; \
+-	 echo " switch(code) {"; \
+-	 $(AWK) "BEGIN{i=0} \
+-	   /^  DNS_$${1}_[A-Z0-9_]+[ 	]*=/ \
+-	   {printf \" case %s: return dns_$${2}tab[%d].name;\\n\",\$$1,i++}\
+-	   " $(srcdir)/source/udns.h ; \
+-	 echo " }"; \
+-	 echo " return _dns_format_code(nm,\"$$2\",code);"; \
+-	 echo "}"; \
+-	 shift 2; \
+-	done
+-	@mv $@.tmp $@
+diff --git a/udns/source/.cvsignore b/udns/source/.cvsignore
+deleted file mode 100644
+index 0714229..0000000
+--- a/udns/source/.cvsignore
++++ /dev/null
+@@ -1,9 +0,0 @@
+-udns*.tar.gz
+-udns_codes.c
+-udns.3.html
+-*.lo
+-*.shared
+-libudns.so.*
+-dnsget
+-ex-rdns
+-rblcheck
+diff --git a/udns/source/COPYING.LGPL b/udns/source/COPYING.LGPL
+deleted file mode 100644
+index b1e3f5a..0000000
+--- a/udns/source/COPYING.LGPL
++++ /dev/null
+@@ -1,504 +0,0 @@
+-		  GNU LESSER GENERAL PUBLIC LICENSE
+-		       Version 2.1, February 1999
+-
+- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+- Everyone is permitted to copy and distribute verbatim copies
+- of this license document, but changing it is not allowed.
+-
+-[This is the first released version of the Lesser GPL.  It also counts
+- as the successor of the GNU Library Public License, version 2, hence
+- the version number 2.1.]
+-
+-			    Preamble
+-
+-  The licenses for most software are designed to take away your
+-freedom to share and change it.  By contrast, the GNU General Public
+-Licenses are intended to guarantee your freedom to share and change
+-free software--to make sure the software is free for all its users.
+-
+-  This license, the Lesser General Public License, applies to some
+-specially designated software packages--typically libraries--of the
+-Free Software Foundation and other authors who decide to use it.  You
+-can use it too, but we suggest you first think carefully about whether
+-this license or the ordinary General Public License is the better
+-strategy to use in any particular case, based on the explanations below.
+-
+-  When we speak of free software, we are referring to freedom of use,
+-not price.  Our General Public Licenses are designed to make sure that
+-you have the freedom to distribute copies of free software (and charge
+-for this service if you wish); that you receive source code or can get
+-it if you want it; that you can change the software and use pieces of
+-it in new free programs; and that you are informed that you can do
+-these things.
+-
+-  To protect your rights, we need to make restrictions that forbid
+-distributors to deny you these rights or to ask you to surrender these
+-rights.  These restrictions translate to certain responsibilities for
+-you if you distribute copies of the library or if you modify it.
+-
+-  For example, if you distribute copies of the library, whether gratis
+-or for a fee, you must give the recipients all the rights that we gave
+-you.  You must make sure that they, too, receive or can get the source
+-code.  If you link other code with the library, you must provide
+-complete object files to the recipients, so that they can relink them
+-with the library after making changes to the library and recompiling
+-it.  And you must show them these terms so they know their rights.
+-
+-  We protect your rights with a two-step method: (1) we copyright the
+-library, and (2) we offer you this license, which gives you legal
+-permission to copy, distribute and/or modify the library.
+-
+-  To protect each distributor, we want to make it very clear that
+-there is no warranty for the free library.  Also, if the library is
+-modified by someone else and passed on, the recipients should know
+-that what they have is not the original version, so that the original
+-author's reputation will not be affected by problems that might be
+-introduced by others.
+-
+-  Finally, software patents pose a constant threat to the existence of
+-any free program.  We wish to make sure that a company cannot
+-effectively restrict the users of a free program by obtaining a
+-restrictive license from a patent holder.  Therefore, we insist that
+-any patent license obtained for a version of the library must be
+-consistent with the full freedom of use specified in this license.
+-
+-  Most GNU software, including some libraries, is covered by the
+-ordinary GNU General Public License.  This license, the GNU Lesser
+-General Public License, applies to certain designated libraries, and
+-is quite different from the ordinary General Public License.  We use
+-this license for certain libraries in order to permit linking those
+-libraries into non-free programs.
+-
+-  When a program is linked with a library, whether statically or using
+-a shared library, the combination of the two is legally speaking a
+-combined work, a derivative of the original library.  The ordinary
+-General Public License therefore permits such linking only if the
+-entire combination fits its criteria of freedom.  The Lesser General
+-Public License permits more lax criteria for linking other code with
+-the library.
+-
+-  We call this license the "Lesser" General Public License because it
+-does Less to protect the user's freedom than the ordinary General
+-Public License.  It also provides other free software developers Less
+-of an advantage over competing non-free programs.  These disadvantages
+-are the reason we use the ordinary General Public License for many
+-libraries.  However, the Lesser license provides advantages in certain
+-special circumstances.
+-
+-  For example, on rare occasions, there may be a special need to
+-encourage the widest possible use of a certain library, so that it becomes
+-a de-facto standard.  To achieve this, non-free programs must be
+-allowed to use the library.  A more frequent case is that a free
+-library does the same job as widely used non-free libraries.  In this
+-case, there is little to gain by limiting the free library to free
+-software only, so we use the Lesser General Public License.
+-
+-  In other cases, permission to use a particular library in non-free
+-programs enables a greater number of people to use a large body of
+-free software.  For example, permission to use the GNU C Library in
+-non-free programs enables many more people to use the whole GNU
+-operating system, as well as its variant, the GNU/Linux operating
+-system.
+-
+-  Although the Lesser General Public License is Less protective of the
+-users' freedom, it does ensure that the user of a program that is
+-linked with the Library has the freedom and the wherewithal to run
+-that program using a modified version of the Library.
+-
+-  The precise terms and conditions for copying, distribution and
+-modification follow.  Pay close attention to the difference between a
+-"work based on the library" and a "work that uses the library".  The
+-former contains code derived from the library, whereas the latter must
+-be combined with the library in order to run.
+-
+-		  GNU LESSER GENERAL PUBLIC LICENSE
+-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+-
+-  0. This License Agreement applies to any software library or other
+-program which contains a notice placed by the copyright holder or
+-other authorized party saying it may be distributed under the terms of
+-this Lesser General Public License (also called "this License").
+-Each licensee is addressed as "you".
+-
+-  A "library" means a collection of software functions and/or data
+-prepared so as to be conveniently linked with application programs
+-(which use some of those functions and data) to form executables.
+-
+-  The "Library", below, refers to any such software library or work
+-which has been distributed under these terms.  A "work based on the
+-Library" means either the Library or any derivative work under
+-copyright law: that is to say, a work containing the Library or a
+-portion of it, either verbatim or with modifications and/or translated
+-straightforwardly into another language.  (Hereinafter, translation is
+-included without limitation in the term "modification".)
+-
+-  "Source code" for a work means the preferred form of the work for
+-making modifications to it.  For a library, complete source code means
+-all the source code for all modules it contains, plus any associated
+-interface definition files, plus the scripts used to control compilation
+-and installation of the library.
+-
+-  Activities other than copying, distribution and modification are not
+-covered by this License; they are outside its scope.  The act of
+-running a program using the Library is not restricted, and output from
+-such a program is covered only if its contents constitute a work based
+-on the Library (independent of the use of the Library in a tool for
+-writing it).  Whether that is true depends on what the Library does
+-and what the program that uses the Library does.
+-  
+-  1. You may copy and distribute verbatim copies of the Library's
+-complete source code as you receive it, in any medium, provided that
+-you conspicuously and appropriately publish on each copy an
+-appropriate copyright notice and disclaimer of warranty; keep intact
+-all the notices that refer to this License and to the absence of any
+-warranty; and distribute a copy of this License along with the
+-Library.
+-
+-  You may charge a fee for the physical act of transferring a copy,
+-and you may at your option offer warranty protection in exchange for a
+-fee.
+-
+-  2. You may modify your copy or copies of the Library or any portion
+-of it, thus forming a work based on the Library, and copy and
+-distribute such modifications or work under the terms of Section 1
+-above, provided that you also meet all of these conditions:
+-
+-    a) The modified work must itself be a software library.
+-
+-    b) You must cause the files modified to carry prominent notices
+-    stating that you changed the files and the date of any change.
+-
+-    c) You must cause the whole of the work to be licensed at no
+-    charge to all third parties under the terms of this License.
+-
+-    d) If a facility in the modified Library refers to a function or a
+-    table of data to be supplied by an application program that uses
+-    the facility, other than as an argument passed when the facility
+-    is invoked, then you must make a good faith effort to ensure that,
+-    in the event an application does not supply such function or
+-    table, the facility still operates, and performs whatever part of
+-    its purpose remains meaningful.
+-
+-    (For example, a function in a library to compute square roots has
+-    a purpose that is entirely well-defined independent of the
+-    application.  Therefore, Subsection 2d requires that any
+-    application-supplied function or table used by this function must
+-    be optional: if the application does not supply it, the square
+-    root function must still compute square roots.)
+-
+-These requirements apply to the modified work as a whole.  If
+-identifiable sections of that work are not derived from the Library,
+-and can be reasonably considered independent and separate works in
+-themselves, then this License, and its terms, do not apply to those
+-sections when you distribute them as separate works.  But when you
+-distribute the same sections as part of a whole which is a work based
+-on the Library, the distribution of the whole must be on the terms of
+-this License, whose permissions for other licensees extend to the
+-entire whole, and thus to each and every part regardless of who wrote
+-it.
+-
+-Thus, it is not the intent of this section to claim rights or contest
+-your rights to work written entirely by you; rather, the intent is to
+-exercise the right to control the distribution of derivative or
+-collective works based on the Library.
+-
+-In addition, mere aggregation of another work not based on the Library
+-with the Library (or with a work based on the Library) on a volume of
+-a storage or distribution medium does not bring the other work under
+-the scope of this License.
+-
+-  3. You may opt to apply the terms of the ordinary GNU General Public
+-License instead of this License to a given copy of the Library.  To do
+-this, you must alter all the notices that refer to this License, so
+-that they refer to the ordinary GNU General Public License, version 2,
+-instead of to this License.  (If a newer version than version 2 of the
+-ordinary GNU General Public License has appeared, then you can specify
+-that version instead if you wish.)  Do not make any other change in
+-these notices.
+-
+-  Once this change is made in a given copy, it is irreversible for
+-that copy, so the ordinary GNU General Public License applies to all
+-subsequent copies and derivative works made from that copy.
+-
+-  This option is useful when you wish to copy part of the code of
+-the Library into a program that is not a library.
+-
+-  4. You may copy and distribute the Library (or a portion or
+-derivative of it, under Section 2) in object code or executable form
+-under the terms of Sections 1 and 2 above provided that you accompany
+-it with the complete corresponding machine-readable source code, which
+-must be distributed under the terms of Sections 1 and 2 above on a
+-medium customarily used for software interchange.
+-
+-  If distribution of object code is made by offering access to copy
+-from a designated place, then offering equivalent access to copy the
+-source code from the same place satisfies the requirement to
+-distribute the source code, even though third parties are not
+-compelled to copy the source along with the object code.
+-
+-  5. A program that contains no derivative of any portion of the
+-Library, but is designed to work with the Library by being compiled or
+-linked with it, is called a "work that uses the Library".  Such a
+-work, in isolation, is not a derivative work of the Library, and
+-therefore falls outside the scope of this License.
+-
+-  However, linking a "work that uses the Library" with the Library
+-creates an executable that is a derivative of the Library (because it
+-contains portions of the Library), rather than a "work that uses the
+-library".  The executable is therefore covered by this License.
+-Section 6 states terms for distribution of such executables.
+-
+-  When a "work that uses the Library" uses material from a header file
+-that is part of the Library, the object code for the work may be a
+-derivative work of the Library even though the source code is not.
+-Whether this is true is especially significant if the work can be
+-linked without the Library, or if the work is itself a library.  The
+-threshold for this to be true is not precisely defined by law.
+-
+-  If such an object file uses only numerical parameters, data
+-structure layouts and accessors, and small macros and small inline
+-functions (ten lines or less in length), then the use of the object
+-file is unrestricted, regardless of whether it is legally a derivative
+-work.  (Executables containing this object code plus portions of the
+-Library will still fall under Section 6.)
+-
+-  Otherwise, if the work is a derivative of the Library, you may
+-distribute the object code for the work under the terms of Section 6.
+-Any executables containing that work also fall under Section 6,
+-whether or not they are linked directly with the Library itself.
+-
+-  6. As an exception to the Sections above, you may also combine or
+-link a "work that uses the Library" with the Library to produce a
+-work containing portions of the Library, and distribute that work
+-under terms of your choice, provided that the terms permit
+-modification of the work for the customer's own use and reverse
+-engineering for debugging such modifications.
+-
+-  You must give prominent notice with each copy of the work that the
+-Library is used in it and that the Library and its use are covered by
+-this License.  You must supply a copy of this License.  If the work
+-during execution displays copyright notices, you must include the
+-copyright notice for the Library among them, as well as a reference
+-directing the user to the copy of this License.  Also, you must do one
+-of these things:
+-
+-    a) Accompany the work with the complete corresponding
+-    machine-readable source code for the Library including whatever
+-    changes were used in the work (which must be distributed under
+-    Sections 1 and 2 above); and, if the work is an executable linked
+-    with the Library, with the complete machine-readable "work that
+-    uses the Library", as object code and/or source code, so that the
+-    user can modify the Library and then relink to produce a modified
+-    executable containing the modified Library.  (It is understood
+-    that the user who changes the contents of definitions files in the
+-    Library will not necessarily be able to recompile the application
+-    to use the modified definitions.)
+-
+-    b) Use a suitable shared library mechanism for linking with the
+-    Library.  A suitable mechanism is one that (1) uses at run time a
+-    copy of the library already present on the user's computer system,
+-    rather than copying library functions into the executable, and (2)
+-    will operate properly with a modified version of the library, if
+-    the user installs one, as long as the modified version is
+-    interface-compatible with the version that the work was made with.
+-
+-    c) Accompany the work with a written offer, valid for at
+-    least three years, to give the same user the materials
+-    specified in Subsection 6a, above, for a charge no more
+-    than the cost of performing this distribution.
+-
+-    d) If distribution of the work is made by offering access to copy
+-    from a designated place, offer equivalent access to copy the above
+-    specified materials from the same place.
+-
+-    e) Verify that the user has already received a copy of these
+-    materials or that you have already sent this user a copy.
+-
+-  For an executable, the required form of the "work that uses the
+-Library" must include any data and utility programs needed for
+-reproducing the executable from it.  However, as a special exception,
+-the materials to be distributed need not include anything that is
+-normally distributed (in either source or binary form) with the major
+-components (compiler, kernel, and so on) of the operating system on
+-which the executable runs, unless that component itself accompanies
+-the executable.
+-
+-  It may happen that this requirement contradicts the license
+-restrictions of other proprietary libraries that do not normally
+-accompany the operating system.  Such a contradiction means you cannot
+-use both them and the Library together in an executable that you
+-distribute.
+-
+-  7. You may place library facilities that are a work based on the
+-Library side-by-side in a single library together with other library
+-facilities not covered by this License, and distribute such a combined
+-library, provided that the separate distribution of the work based on
+-the Library and of the other library facilities is otherwise
+-permitted, and provided that you do these two things:
+-
+-    a) Accompany the combined library with a copy of the same work
+-    based on the Library, uncombined with any other library
+-    facilities.  This must be distributed under the terms of the
+-    Sections above.
+-
+-    b) Give prominent notice with the combined library of the fact
+-    that part of it is a work based on the Library, and explaining
+-    where to find the accompanying uncombined form of the same work.
+-
+-  8. You may not copy, modify, sublicense, link with, or distribute
+-the Library except as expressly provided under this License.  Any
+-attempt otherwise to copy, modify, sublicense, link with, or
+-distribute the Library is void, and will automatically terminate your
+-rights under this License.  However, parties who have received copies,
+-or rights, from you under this License will not have their licenses
+-terminated so long as such parties remain in full compliance.
+-
+-  9. You are not required to accept this License, since you have not
+-signed it.  However, nothing else grants you permission to modify or
+-distribute the Library or its derivative works.  These actions are
+-prohibited by law if you do not accept this License.  Therefore, by
+-modifying or distributing the Library (or any work based on the
+-Library), you indicate your acceptance of this License to do so, and
+-all its terms and conditions for copying, distributing or modifying
+-the Library or works based on it.
+-
+-  10. Each time you redistribute the Library (or any work based on the
+-Library), the recipient automatically receives a license from the
+-original licensor to copy, distribute, link with or modify the Library
+-subject to these terms and conditions.  You may not impose any further
+-restrictions on the recipients' exercise of the rights granted herein.
+-You are not responsible for enforcing compliance by third parties with
+-this License.
+-
+-  11. If, as a consequence of a court judgment or allegation of patent
+-infringement or for any other reason (not limited to patent issues),
+-conditions are imposed on you (whether by court order, agreement or
+-otherwise) that contradict the conditions of this License, they do not
+-excuse you from the conditions of this License.  If you cannot
+-distribute so as to satisfy simultaneously your obligations under this
+-License and any other pertinent obligations, then as a consequence you
+-may not distribute the Library at all.  For example, if a patent
+-license would not permit royalty-free redistribution of the Library by
+-all those who receive copies directly or indirectly through you, then
+-the only way you could satisfy both it and this License would be to
+-refrain entirely from distribution of the Library.
+-
+-If any portion of this section is held invalid or unenforceable under any
+-particular circumstance, the balance of the section is intended to apply,
+-and the section as a whole is intended to apply in other circumstances.
+-
+-It is not the purpose of this section to induce you to infringe any
+-patents or other property right claims or to contest validity of any
+-such claims; this section has the sole purpose of protecting the
+-integrity of the free software distribution system which is
+-implemented by public license practices.  Many people have made
+-generous contributions to the wide range of software distributed
+-through that system in reliance on consistent application of that
+-system; it is up to the author/donor to decide if he or she is willing
+-to distribute software through any other system and a licensee cannot
+-impose that choice.
+-
+-This section is intended to make thoroughly clear what is believed to
+-be a consequence of the rest of this License.
+-
+-  12. If the distribution and/or use of the Library is restricted in
+-certain countries either by patents or by copyrighted interfaces, the
+-original copyright holder who places the Library under this License may add
+-an explicit geographical distribution limitation excluding those countries,
+-so that distribution is permitted only in or among countries not thus
+-excluded.  In such case, this License incorporates the limitation as if
+-written in the body of this License.
+-
+-  13. The Free Software Foundation may publish revised and/or new
+-versions of the Lesser General Public License from time to time.
+-Such new versions will be similar in spirit to the present version,
+-but may differ in detail to address new problems or concerns.
+-
+-Each version is given a distinguishing version number.  If the Library
+-specifies a version number of this License which applies to it and
+-"any later version", you have the option of following the terms and
+-conditions either of that version or of any later version published by
+-the Free Software Foundation.  If the Library does not specify a
+-license version number, you may choose any version ever published by
+-the Free Software Foundation.
+-
+-  14. If you wish to incorporate parts of the Library into other free
+-programs whose distribution conditions are incompatible with these,
+-write to the author to ask for permission.  For software which is
+-copyrighted by the Free Software Foundation, write to the Free
+-Software Foundation; we sometimes make exceptions for this.  Our
+-decision will be guided by the two goals of preserving the free status
+-of all derivatives of our free software and of promoting the sharing
+-and reuse of software generally.
+-
+-			    NO WARRANTY
+-
+-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+-
+-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+-DAMAGES.
+-
+-		     END OF TERMS AND CONDITIONS
+-
+-           How to Apply These Terms to Your New Libraries
+-
+-  If you develop a new library, and you want it to be of the greatest
+-possible use to the public, we recommend making it free software that
+-everyone can redistribute and change.  You can do so by permitting
+-redistribution under these terms (or, alternatively, under the terms of the
+-ordinary General Public License).
+-
+-  To apply these terms, attach the following notices to the library.  It is
+-safest to attach them to the start of each source file to most effectively
+-convey the exclusion of warranty; and each file should have at least the
+-"copyright" line and a pointer to where the full notice is found.
+-
+-    <one line to give the library's name and a brief idea of what it does.>
+-    Copyright (C) <year>  <name of author>
+-
+-    This library is free software; you can redistribute it and/or
+-    modify it under the terms of the GNU Lesser General Public
+-    License as published by the Free Software Foundation; either
+-    version 2.1 of the License, or (at your option) any later version.
+-
+-    This library 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
+-    Lesser General Public License for more details.
+-
+-    You should have received a copy of the GNU Lesser General Public
+-    License along with this library; if not, write to the Free Software
+-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+-
+-Also add information on how to contact you by electronic and paper mail.
+-
+-You should also get your employer (if you work as a programmer) or your
+-school, if any, to sign a "copyright disclaimer" for the library, if
+-necessary.  Here is a sample; alter the names:
+-
+-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+-
+-  <signature of Ty Coon>, 1 April 1990
+-  Ty Coon, President of Vice
+-
+-That's all there is to it!
+-
+-
+diff --git a/udns/source/Makefile b/udns/source/Makefile
+deleted file mode 100755
+index d2754fd..0000000
+--- a/udns/source/Makefile
++++ /dev/null
+@@ -1,132 +0,0 @@
+-#! /usr/bin/make -rf
+-# $Id: Makefile,v 1.42 2006/11/29 21:27:01 mjt Exp $
+-# libudns Makefile
+-#
+-# Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-# This file is part of UDNS library, an async DNS stub resolver.
+-#
+-# This library is free software; you can redistribute it and/or
+-# modify it under the terms of the GNU Lesser General Public
+-# License as published by the Free Software Foundation; either
+-# version 2.1 of the License, or (at your option) any later version.
+-#
+-# This library 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
+-# Lesser General Public License for more details.
+-#
+-# You should have received a copy of the GNU Lesser General Public
+-# License along with this library, in file named COPYING.LGPL; if not,
+-# write to the Free Software Foundation, Inc., 59 Temple Place,
+-# Suite 330, Boston, MA  02111-1307  USA
+-
+-VERS   = 0.0.9pre
+-SRCS   = udns_dn.c udns_dntosp.c udns_parse.c udns_resolver.c udns_misc.c \
+-	udns_rr_a.c udns_rr_ptr.c udns_rr_mx.c udns_rr_txt.c udns_bl.c \
+-	udns_rr_srv.c udns_rr_naptr.c udns_codes.c
+-USRCS  = dnsget.c rblcheck.c ex-rdns.c
+-DEB    = debian/copyright debian/changelog debian/control debian/rules
+-DIST   = COPYING.LGPL udns.h udns.3 dnsget.1 rblcheck.1 $(SRCS) $(USRCS) \
+-	Makefile TODO NOTES
+-
+-OBJS   = $(SRCS:.c=.o) $(GEN:.c=.o)
+-LIB    = libudns.a
+-
+-SOVER  = 0
+-SOBJS  = $(OBJS:.o=.lo)
+-SOLIB  = libudns.so
+-SOLIBV = $(SOLIB).$(SOVER)
+-
+-LIBS   = $(LIB) $(SOLIBV)
+-
+-UTILS   = $(USRCS:.c=)
+-SOUTILS = $(USRCS:.c=.shared)
+-
+-NAMEPFX = udns-$(VERS)
+-
+-CC = gcc
+-CFLAGS = -Wall -W -Wmissing-prototypes -O2
+-CDEFS = -DHAVE_POLL
+-PICFLAGS = -fPIC
+-AWK = awk
+-
+-all: static
+-
+-.SUFFIXES: .c .o .lo .shared
+-
+-static: $(LIB) $(UTILS)
+-staticlib: $(LIB)
+-$(LIB): $(OBJS)
+-	-rm -f $@
+-	$(AR) rv $@ $(OBJS)
+-.c.o:
+-	$(CC) $(CFLAGS) $(CDEFS) -c $<
+-$(OBJS): udns.h
+-
+-$(UTILS): udns.h $(LIB)
+-.c:
+-	$(CC) $(CFLAGS) $(CDEFS) -o $@ $< $(LIB)
+-
+-shared: $(SOLIBV) $(SOUTILS)
+-sharedlib: $(SOLIBV)
+-
+-$(SOLIBV): $(SOBJS)
+-	$(CC) -shared -Wl,--soname,$(SOLIBV) -o $@ $(SOBJS)
+-	rm -f $(SOLIB)
+-	ln -s $(SOLIBV) $(SOLIB)
+-.c.lo:
+-	$(CC) $(CFLAGS) $(PICFLAGS) $(CDEFS) -o $@ -c $<
+-$(SOBJS): udns.h
+-
+-$(SOUTILS): udns.h $(SOLIB)
+-.c.shared:
+-	$(CC) $(CFLAGS) $(CDEFS) -o $@ $< $(SOLIB)
+-
+-# udns_codes.c is generated from udns.h
+-udns_codes.c:	udns.h Makefile
+-	@echo Generating $@
+-	@set -e; exec >$@.tmp; \
+-	set T type C class R rcode; \
+-	echo "/* Automatically generated. */"; \
+-	echo "#include \"udns.h\""; \
+-	while [ "$$1" ]; do \
+-	 echo; \
+-	 echo "const struct dns_nameval dns_$${2}tab[] = {"; \
+-	 $(AWK) "/^  DNS_$${1}_[A-Z0-9_]+[ 	]*=/ \
+-	  { printf \" {%s,\\\"%s\\\"},\\n\", \$$1, substr(\$$1,7) }" \
+-	  udns.h ; \
+-	 echo " {0,0}};"; \
+-	 echo "const char *dns_$${2}name(enum dns_$${2} code) {"; \
+-	 echo " static char nm[20];"; \
+-	 echo " switch(code) {"; \
+-	 $(AWK) "BEGIN{i=0} \
+-	   /^  DNS_$${1}_[A-Z0-9_]+[ 	]*=/ \
+-	   {printf \" case %s: return dns_$${2}tab[%d].name;\\n\",\$$1,i++}\
+-	   " udns.h ; \
+-	 echo " }"; \
+-	 echo " return _dns_format_code(nm,\"$$2\",code);"; \
+-	 echo "}"; \
+-	 shift 2; \
+-	done
+-	@mv $@.tmp $@
+-
+-udns.3.html: udns.3
+-	groff -man -Thtml udns.3 > $@.tmp
+-	mv $@.tmp $@
+-
+-dist: $(NAMEPFX).tar.gz
+-$(NAMEPFX).tar.gz: $(DIST) $(DEB)
+-	mkdir $(NAMEPFX) $(NAMEPFX)/debian
+-	ln $(DIST) $(NAMEPFX)
+-	ln $(DEB) $(NAMEPFX)/debian
+-	tar cvfz $@ $(NAMEPFX)
+-	rm -rf $(NAMEPFX)
+-subdist:
+-	cp -p $(DIST) $(TARGET)/
+-
+-clean:
+-	rm -f $(OBJS) $(SOBJS) build-stamp
+-distclean: clean
+-	rm -f $(LIBS) libudns.so udns.3.html $(UTILS) $(SOUTILS)
+-
+-.PHONY: all static staticlib shared sharedlib dist clean distclean subdist
+diff --git a/udns/source/NEWS b/udns/source/NEWS
+deleted file mode 100644
+index 51cfd6c..0000000
+--- a/udns/source/NEWS
++++ /dev/null
+@@ -1,53 +0,0 @@
+-$Id: NEWS,v 1.6 2005/09/12 12:09:10 mjt Exp $
+-
+-User-visible changes in udns library.  Recent changes on top.
+-
+-0.0.8 (12 Sep 2005)
+-
+- - added SRV records (rfc2782) parsing,
+-   thanks to Thadeu Lima de Souza Cascardo for implementation.
+-
+- - bugfixes:
+-   o use uninitialized value when no reply, library died with assertion:
+-     assert((status < 0 && result == 0) || (status >= 0 && result != 0)).
+-   o on some OSes, struct sockaddr_in has additional fields, so
+-     memcmp'ing two sockaddresses does not work.
+-
+- - rblcheck(.1)
+-
+-0.0.7 (20 Apr 2005)
+-
+- - dnsget.1 manpage and several enhancements to dnsget.
+-
+- - allow nameserver names for -n option of dnsget.
+-
+- - API change: all dns_submit*() routines now does not expect
+-   last `now' argument, since requests aren't sent immediately
+-   anymore.
+-
+- - API change: different application timer callback mechanism.
+-   Udns now uses single per-context timer instead of per-query.
+-
+- - don't assume DNS replies only contain backward DN pointers,
+-   allow forward pointers too.  Change parsing API.
+-
+- - debianize
+-
+-0.0.6 (08 Apr 2005)
+-
+- - use double sorted list for requests (sorted by deadline).
+-   This should significantly speed up timeout processing for
+-   large number of requests.
+-
+- - changed debugging interface, so it is finally useable
+-   (still not documented).
+-
+- - dnsget routine is now Officially Useable, and sometimes
+-   even more useable than `host' from BIND distribution
+-   (and sometimes not - dnsget does not have -C option
+-   and TCP mode)
+-
+- - Debian packaging in debian/ -- udns is now maintained as a
+-   native Debian package.
+-
+- - alot (and I really mean alot) of code cleanups all over.
+diff --git a/udns/source/NOTES b/udns/source/NOTES
+deleted file mode 100644
+index 3fe75c1..0000000
+--- a/udns/source/NOTES
++++ /dev/null
+@@ -1,193 +0,0 @@
+-Assorted notes about udns (library).
+-
+-UDP-only mode
+-~~~~~~~~~~~~~
+-
+-First of all, since udns is (currently) UDP-only, there are some
+-shortcomings.
+-
+-It assumes that a reply will fit into a UDP buffer.  With adoption of EDNS0,
+-and general robustness of IP stacks, in most cases it's not an issue.  But
+-in some cases there may be problems:
+-
+- - if an RRset is "very large" so it does not fit even in buffer of size
+-   requested by the library (current default is 4096; some servers limits
+-   it further), we will not see the reply, or will only see "damaged"
+-   reply (depending on the server)
+-
+- - many DNS servers ignores EDNS0 option requests.  In this case, no matter
+-   which buffer size udns library will request, such servers reply is limited
+-   to 512 bytes (standard pre-EDNS0 DNS packet size).
+-
+- - some DNS servers, notable the ones used by Verisign for certain top-level
+-   domains, chokes on EDNS0-enabled queries, returning FORMERR.  Such
+-   behavior isn't prohibited by DNS standards, but in my opinion it's at
+-   least weird - the server can easily ignore EDNS0 options and send a
+-   reply, instead of sending error.
+-   Currently, udns does nothing in this situation, completely ignoring the
+-   error returned by the server, and continue waiting for reply.  It probably
+-   should grok that this server does not understand EDNS0 and retry w/o the
+-   options, but it does not.  The end result - esp. if your local DNS
+-   server or - worse - broken firewall which inspects DNS packets and drops
+-   the ones which - from its point of view - are "broken" - is that you
+-   see only TEMPFAIL errors from the library trying to resolve ANY names.
+-
+-Implementing TCP mode (together with non-EDNS0 fall-back as above) isn't
+-difficult, but it complicates API significantly.  Currently udns uses only
+-single UDP socket (or - maybe in the future - two, see below), but in case of
+-TCP, it will need to open and close sockets for TCP connections left and
+-right, and that have to be integrated into an application's event loop in
+-an easy and efficient way.  Plus all the timeouts - different for connect(),
+-write, and several stages of read.
+-
+-IPv6 vs IPv4 usage
+-~~~~~~~~~~~~~~~~~~
+-
+-This is only relevant for nameservers reachable over IPv6, NOT for IPv6
+-queries.  I.e., if you've IPv6 addresses in 'nameservers' line in your
+-/etc/resolv.conf file.  Even more: if you have BOTH IPv6 AND IPv4 addresses
+-there.  Or pass them to udns initialization routines.
+-
+-Since udns uses a single UDP socket to communicate with all nameservers,
+-it should support both v4 and v6 communications.  Most current platforms
+-supports this mode - using PF_INET6 socket and V4MAPPED addresses, i.e,
+-"tunnelling" IPv4 inside IPv6.  But not all systems supports this.  And
+-more, it has been said that such mode is deprecated.
+-
+-So, list only IPv4 or only IPv6 addresses, but don't mix them, in your
+-/etc/resolv.conf.
+-
+-An alternative is to use two sockets instead of 1 - one for IPv6 and one
+-for IPv4.  For now I'm not sure if it's worth the complexity - again, of
+-the API, not the library itself (but this will not simplify library either).
+-
+-Single socket for all queries
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-Using single UDP socket for sending queries to all nameservers has obvious
+-advantages.  First it's, again, trivial, simple to use API.  And simple
+-library too.  Also, after sending queries to all nameservers (in case first
+-didn't reply in time), we will be able to receive late reply from first
+-nameserver and accept it.
+-
+-But this mode has disadvantages too.  Most important is that it's much easier
+-to send fake reply to us, as the UDP port where we expects the reply to come
+-to is constant during the whole lifetime of an application.  More secure
+-implementations uses random port for every single query.  While port number
+-(16 bits integer) can not hold much randomness, it's still of some help.
+-Ok, udns is a stub resolver, so it expects sorta friendly environment, but
+-on LAN it's usually much easier to fire an attack, due to the speed of local
+-network, where a bad guy can generate alot of packets in a short time.
+-
+-Choosing of DNS QueryID
+-~~~~~~~~~~~~~~~~~~~~~~~
+-
+-This is more a TODO item really.  Currently, udns uses sequential number for
+-query IDs.  Which simplifies attacks even more (c.f. the previous item about
+-single UDP port), making them nearly trivial.  The library should use random
+-number for query ID.  But there's no portable way to get random numbers, even
+-on various flavors of Unix.  It's possible to use low bits from tv_nsec field
+-returned by gettimeofday() (current time, nanoseconds), but I wrote the library
+-in a way to avoid making system calls where possible, because many syscalls
+-means many context switches and slow processes as a result.  Maybe use some
+-application-supplied callback to get random values will be a better way,
+-defaulting to gettimeofday() method.
+-
+-Note that a single query - even if (re)sent to different nameservers, several
+-times (due to no reply received in time), uses the same qID assigned when it
+-was first dispatched.  So we have: single UDP socket (fixed port number),
+-sequential (= trivially predictable) qIDs, and long lifetime of those qIDs.
+-This all makes (local) attacks against the library really trivial.
+-
+-Assumptions about RRs returned
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-Currently udns processes records in the reply it received sequentially.
+-This means that order of the records is significant.  For example, if
+-we asked for foo.bar A, but the server returned that foo.bar is a CNAME
+-(alias) for bar.baz, and bar.baz, in turn, has address 1.2.3.4, when
+-the CNAME should come first in reply, followed by A.  While DNS specs
+-does not say anything about order of records - it's an rrSET - unordered, -
+-I think an implementation which returns the records in "wrong" order is
+-somewhat insane...  Well ok, to be fair, I don't really remember how
+-udns handles this now - need to check this in source... ;)
+-
+-CNAME recursion
+-~~~~~~~~~~~~~~~
+-
+-Another dark point of udns is the handling of CNAMEs returned as replies
+-to non-CNAME queries.  If we asked for foo.bar A, but it's a CNAME, udns
+-expects BOTH the CNAME itself and the target DN to be present in the reply.
+-In other words, udns DOES NOT RECURSE CNAMES.  If we asked for foo.bar A,
+-but only record in reply was that foo.bar is a CNAME for bar.baz, udns will
+-return no records to an application (NXDOMAIN).  Strictly speaking, udns
+-should repeat the query asking for bar.baz A, and recurse.  But since it's
+-stub resolver, recursive resolver should recurse for us instead.
+-
+-It's not very difficult to implement, however.  Probably with some (global?)
+-flag to en/dis-able the feature.  Provided there's some demand for it.
+-
+-To clarify: udns handles CNAME recursion in a single reply packet just fine.
+-
+-Error reporting
+-~~~~~~~~~~~~~~~
+-
+-Too many places in the code (various failure paths) sets generic "TEMPFAIL"
+-error condition.  For example, if no nameserver replied to our query, an
+-application will get generic TEMPFAIL, instead of something like TIMEDOUT.
+-This probably should be fixed, but most applications don't care about the
+-exact reasons of failure - 4 common cases are already too much:
+-  - query returned some valid data
+-  - NXDOMAIN
+-  - valid domain but no data of requested type - =NXDOMAIN in most cases
+-  - temporary error - this one sometimes (incorrectly!) treated as NXDOMAIN
+-    by (naive) applications.
+-DNS isn't yes/no, it's at least 3 variants, temp err being the 3rd important
+-case!  And adding more variations for the temp error case is complicating things
+-even more - again, from an application writer standpoint.  For diagnostics,
+-such more specific error cases are of good help.
+-
+-Planned API changes
+-~~~~~~~~~~~~~~~~~~~
+-
+-At least one thing I want to change for 0.1 version is a way how queries are
+-submitted.
+-
+-I want to made dns_query object to be owned by an application.  So that instead
+-of udns library allocating it for the lifetime of query, it will be pre-
+-allocated by an application.  This simplifies and enhances query submitting
+-interface, and complicates it a bit too, in simplest cases.
+-
+-Currently, we have:
+-
+-dns_submit_dn(dn, cls, typ, flags, parse, cbck, data)
+-dns_submit_p(name, cls, typ, flags, parse, cbck, data)
+-dns_submit_a4(ctx, name, flags, cbck, data)
+-
+-and so on -- with many parameters missed for type-specific cases, but generic
+-cases being too complex for most common usage.
+-
+-Instead, with dns_query being owned by an app, we will be able to separately
+-set up various parts of the query - domain name (various forms), type&class,
+-parser, flags, callback...  and even change them at runtime.  And we will also
+-be able to reuse query structures, instead of allocating/freeing them every
+-time.  So the whole thing will look something like:
+-
+- q = dns_alloc_query();
+- dns_submit(dns_q_flags(dns_q_a4(q, name, cbck), DNS_F_NOSRCH), data);
+-
+-The idea is to have a set of functions accepting struct dns_query* and
+-returning it (so the calls can be "nested" like the above), to set up
+-relevant parts of the query - specific type of callback, conversion from
+-(type-specific) query parameters into a domain name (this is for type-
+-specific query initializers), and setting various flags and options and
+-type&class things.
+-
+-One example where this is almost essential - if we want to support
+-per-query set of nameservers (which isn't at all useless: imagine a
+-high-volume mail server, were we want to direct DNSBL queries to a separate
+-set of nameservers, and rDNS queries to their own set and so on).  Adding
+-another argument (set of nameservers to use) to EVERY query submitting
+-routine is.. insane.  Especially since in 99% cases it will be set to
+-default NULL.  But with such "nesting" of query initializers, it becomes
+-trivial.
+diff --git a/udns/source/TODO b/udns/source/TODO
+deleted file mode 100644
+index ce5bba1..0000000
+--- a/udns/source/TODO
++++ /dev/null
+@@ -1,74 +0,0 @@
+-$Id: TODO,v 1.10 2005/04/19 21:48:09 mjt Exp $
+-
+-The following is mostly an internal, not user-visible stuff.
+-
+-* rearrange an API to make dns_query object owned by application,
+-  so that it'll look like this:
+-   struct dns_query *q;
+-   q = udns_query_alloc(ctx);
+-   udns_query_set(q, options, domain_name, flags, ...);
+-   udns_query_submit(ctx, q);
+- or
+-   udns_query_resolve(ctx, q);
+-
+-* allow NULL callbacks?  Or provide separate resolver
+-  context list of queries which are done but wich did not
+-  have callback, and dns_pick() routine to retrieve results
+-  from this query, i.e. allow non-callback usage?  The
+-  non-callback usage may be handy sometimes (any *good*
+-  example?), but it will be difficult to provide type-safe
+-  non-callback interface due to various RR-specific types
+-  in use.
+-
+-* DNS_OPT_FLAGS should be DNS_OPT_ADDFLAGS and DNS_OPT_SETFLAGS.
+-  Currently one can't add a single flag bit but preserve
+-  existing bits... at least not without retrieving all current
+-  flags before, which isn't that bad anyway.
+-
+-* dns_set_opts() may process flags too (such as aaonly etc)
+-
+-* a way to disable $NSCACHEIP et al processing?
+-
+-* initialize/open the context automatically, and be more
+-  liberal about initialization in general?
+-
+-* dns_init(do_open) - make the parameter opposite, aka
+-  dns_init(skip_open) ?
+-
+-* for the above.  Use separate routine for initializing the context
+-  from system files, to not link stuff reading resolv.conf if it's
+-  not needed.  So that automatic init will not be possible.
+-
+-* allow TCP queue?
+-
+-* detect servers which don't understand EDNS0 (returning FORMERR),
+-  and fall back to pre-EDNS0 for them.
+-
+-* for the above to work, we have to be able to find query object by
+-  only ID, not ID + qdn.
+-
+-* And oh, qID should really be random.
+-
+-* more accurate error reporting.  Currently, udns always returns TEMPFAIL,
+-  but don't specify why it happened (ENOMEM, timeout, etc).
+-
+-* check the error value returned by recvfrom() and
+-  sendto() and determine which errors to ignore.
+-
+-* maybe merge dns_timeouts() and dns_ioevent(), to have
+-  only one entry point for everything?  For traditional
+-  select-loop-based eventloop it may be easier, but for
+-  callback-driven event loops the two should be separate.
+-  Provide an option, or a single dns_events() entry point
+-  for select-loop approach, or just call dns_ioevent()
+-  from within dns_timeouts() (probably after renaming
+-  it to be dns_events()) ?
+-
+-* implement /etc/hosts lookup too, ala [c-]ares??
+-
+-* sortlist support?
+-
+-* windows port?  Oh no please!..  At least, I can't do it myself
+-  because of the lack of platform.
+-  Ok ok, the Windows port is in progress.  Christian Prahauser
+-  from cosy.sbg.ac.at is helping with that.
+diff --git a/udns/source/debian/changelog b/udns/source/debian/changelog
+deleted file mode 100644
+index c393fea..0000000
+--- a/udns/source/debian/changelog
++++ /dev/null
+@@ -1,94 +0,0 @@
+-udns (0.0.9pre) unstable; urgency=low
+-
+-  * s/EOVERFLOW/ENFILE, partly to make win32 happy
+-
+-  * several win32 fixes
+-
+-  * don't use `class' in udns.h, to make C++ happy
+-    (thanks Markus Koetter for pointing this out)
+-
+-  * fixed CNAME handling in dnsget tool.  Another Thank You! goes
+-    to Markus Koetter.
+-
+-  * NAPTR (RFC3403) support, thanks to Mikael Magnusson
+-    <mikma at users.sourceforge.net> for this.
+-
+-  * more Win32 fixes from Mikael Magnusson.  I have to admit
+-    I never tried to compile it on Win32.
+-
+-  * added NOTES file
+-
+- -- Michael Tokarev <mjt at corpit.ru>  Wed, 29 Nov 2006 04:16:21 +0300
+-
+-udns (0.0.8) unstable; urgency=low
+-
+-  * don't compare sockaddr_in's, but individual parts only
+-    (on some OSes, there are additional fields in this structure
+-    so memcmp() does not quite work)
+-
+-  * use dnsc_t instead of unsigned char for DNs everywhere
+-
+-  * SRV records (rfc2782) parsing, thanks to
+-    Thadeu Lima de Souza Cascardo.
+-
+-  * manpage fixes
+-
+- -- Michael Tokarev <mjt at corpit.ru>  Mon, 12 Sep 2005 16:06:45 +0400
+-
+-udns (0.0.7) unstable; urgency=low
+-
+-  * added dnsget.1 and rblcheck.1 manpages.
+-
+-  * internal: use generic list implementation in udns_resolver.c
+-
+-  * don't assume only backward DN pointers in replies, allow forward
+-    pointers too.  This is quite large change, involves changing
+-    parsing API all over the places.
+-
+-  * internal: typedef dnsc_t and dnscc_t for [const] unsigned char, to
+-    make function prototypes shorter to better fit on a single line.
+-
+-  * in parsing routines, verify (assert) that the query type
+-    is the one we can handle.
+-
+-  * recognize names (and resolve them) as nameservers in dnsget.
+-
+-  * when new request is submitted, don't send it immediately, but
+-    add it into the head of the active queue with deadline=0.
+-    This will allow us to tweak some query settings before it will
+-    be processed.
+-    Note API change: removed `now' argument from all dns_submit_*()
+-    routines.
+-
+-  * use single per-context user timer, not per-query.
+-    Note API change: different user timer callback
+-
+-  * add dnsc_salen field -- length of the socket address used
+-
+-  * fix dns_set_opt(DNS_OPT_FLAGS) which didn't work before
+-
+-  * allow to set some options for a context wich is open but with no
+-    active queries
+-
+- -- Michael Tokarev <mjt at corpit.ru>  Thu,  5 May 2005 23:14:29 +0400
+-
+-udns (0.0.6) unstable; urgency=low
+-
+-  * 0.0.6 release.
+-    ALOT of changes all over.  Keep 'em in CVS logs!
+-
+- -- Michael Tokarev <mjt at corpit.ru>  Fri,  8 Apr 2005 19:51:38 +0400
+-
+-udns (0.0.5) unstable; urgency=low
+-
+-  * Initial Release.
+-  * Provides 3 packages:
+-     libudns0 - shared library
+-     libudns-dev - development files and static library
+-     udns-utils - dnsget, rblcheck
+-
+- -- Michael Tokarev <mjt at corpit.ru>  Thu,  7 Apr 2005 00:05:24 +0400
+-
+-Local variables:
+-mode: debian-changelog
+-End:
+diff --git a/udns/source/debian/control b/udns/source/debian/control
+deleted file mode 100644
+index f7234f5..0000000
+--- a/udns/source/debian/control
++++ /dev/null
+@@ -1,33 +0,0 @@
+-Source: udns
+-Priority: optional
+-Maintainer: Michael Tokarev <mjt at corpit.ru>
+-Build-Depends: debhelper (>= 4.0.0)
+-Standards-Version: 3.6.1
+-
+-Package: libudns0
+-Section: lib
+-Architecture: any
+-Depends: ${shlibs:Depends}
+-Description: async-capable DNS stub resolver library
+- libudns0 package provides libudns shared library needed
+- to run programs using it
+-
+-Package: libudns-dev
+-Section: libdev
+-Architecture: any
+-Depends: libudns0 (= ${Source-Version})
+-Description: async-capable DNS stub resolver library, development files
+- This package provides development files needed
+- to build programs using udns library
+-
+-Package: udns-utils
+-Section: net
+-Architecture: any
+-Depends: ${shlibs:Depends}
+-Conflicts: rblcheck
+-Description: Several DNS-related utilities built on top of udns library
+- This package includes the following utilities:
+-  dnsget - a simple DNS query tool, like `host' or `dig' for usage from
+-   a command line, and dnsip, dnsname etc for usage in scripts
+-  rblcheck - DNSBL (rbl) checker
+- All the utilities are built using udns library
+diff --git a/udns/source/debian/copyright b/udns/source/debian/copyright
+deleted file mode 100644
+index 089491b..0000000
+--- a/udns/source/debian/copyright
++++ /dev/null
+@@ -1,24 +0,0 @@
+-This is udns, written and maintained by Michael Tokarev <mjt at corpit.ru>
+-
+-The original source can always be found at:
+-	http://www.corpit.ru/mjt/udns.html
+-
+-Copyright (C) 2005  Michael Tokarev
+-
+-  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 2 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 package; if not, write to the Free Software
+-  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+-  02111-1307, USA.
+-
+-On Debian systems, the complete text of the GNU General
+-Public License can be found in `/usr/share/common-licenses/GPL'.
+diff --git a/udns/source/debian/rules b/udns/source/debian/rules
+deleted file mode 100755
+index 07dc8b8..0000000
+--- a/udns/source/debian/rules
++++ /dev/null
+@@ -1,91 +0,0 @@
+-#!/usr/bin/make -f
+-# -*- makefile -*-
+-# This file was originally written by Joey Hess and Craig Small.
+-# As a special exception, when this file is copied by dh-make into a
+-# dh-make output file, you may use that output file without restriction.
+-# This special exception was added by Craig Small in version 0.37 of dh-make.
+-
+-# Uncomment this to turn on verbose mode.
+-#export DH_VERBOSE=1
+-export DH_COMPAT=4
+-
+-CFLAGS = -Wall -W -Wmissing-prototypes -g
+-CDEFS = -DHAVE_POOL
+-
+-INSTALL = install
+-INSTALL_PROGRAM = $(INSTALL) -p
+-INSTALL_DATA = $(INSTALL) -p -m0644
+-
+-ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+-	CFLAGS += -O0
+-else
+-	CFLAGS += -O2
+-endif
+-ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
+-	INSTALL_PROGRAM += -s
+-endif
+-ifeq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
+-#	CDEFS += -DNDEBUG
+-endif
+-
+-SOVER = 0
+-
+-configure:	# nothing
+-	dh_testdir
+-
+-build:	build-stamp
+-build-stamp:
+-	dh_testdir
+-	$(MAKE) CFLAGS="$(CFLAGS)" CDEFS="$(CDEFS)" SOVER=$(SOVER) \
+-		staticlib sharedlib rblcheck.shared dnsget.shared
+-	mv -f rblcheck.shared rblcheck
+-	mv -f dnsget.shared dnsget
+-	touch $@
+-
+-clean:
+-	dh_testdir
+-	rm -f build-stamp
+-	$(MAKE) distclean
+-	dh_clean
+-
+-install: build
+-	dh_testdir
+-	dh_testroot
+-	dh_clean
+-	dh_installdirs
+-	dh_installdocs -A NEWS
+-
+-# libudns
+-	dh_install -plibudns$(SOVER) libudns.so.$(SOVER) usr/lib
+-
+-# libudns-dev
+-	dh_install -plibudns-dev libudns.a libudns.so usr/lib
+-	dh_install -plibudns-dev udns.h usr/include
+-	dh_installman -plibudns-dev udns.3
+-	dh_installdocs -plibudns-dev TODO NOTES
+-	dh_installexamples -plibudns-dev ex-rdns.c
+-
+-# udns-utils
+-	dh_installdirs -pudns-utils usr/bin
+-	dh_install -pudns-utils dnsget rblcheck usr/bin
+-	dh_installman -pudns-utils dnsget.1 rblcheck.1
+-
+-binary-indep: build install
+-
+-binary-arch: build install
+-	dh_testdir
+-	dh_testroot
+-	dh_installchangelogs
+-	dh_installdocs
+-	dh_strip
+-	dh_compress
+-	dh_fixperms
+-	dh_makeshlibs
+-	dh_installdeb
+-	dh_shlibdeps -L libudns$(SOVER) -l debian/libudns$(SOVER)/usr/lib
+-	dh_gencontrol
+-	dh_md5sums
+-	dh_builddeb
+-
+-binary: binary-indep binary-arch
+-.PHONY: build clean binary-indep binary-arch binary install configure
+diff --git a/udns/source/dnsget.1 b/udns/source/dnsget.1
+deleted file mode 100644
+index 711f297..0000000
+--- a/udns/source/dnsget.1
++++ /dev/null
+@@ -1,182 +0,0 @@
+-.\" $Id: dnsget.1,v 1.3 2005/04/20 00:55:34 mjt Exp $
+-.\" dnsget manpage
+-.\"
+-.\" Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-.\" This file is part of UDNS library, an async DNS stub resolver.
+-.\"
+-.\" This library is free software; you can redistribute it and/or
+-.\" modify it under the terms of the GNU Lesser General Public
+-.\" License as published by the Free Software Foundation; either
+-.\" version 2.1 of the License, or (at your option) any later version.
+-.\"
+-.\" This library 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
+-.\" Lesser General Public License for more details.
+-.\"
+-.\" You should have received a copy of the GNU Lesser General Public
+-.\" License along with this library, in file named COPYING.LGPL; if not,
+-.\" write to the Free Software Foundation, Inc., 59 Temple Place,
+-.\" Suite 330, Boston, MA  02111-1307  USA
+-
+-.TH dnsget 1 "Apr 2005" "User Utilities"
+-
+-.SH NAME
+-dnsget \- DNS lookup utility
+-
+-.SH SYNOPSYS
+-.B dnsget
+-.RB [\| \-v \||\| \-q \|]
+-.RB [\| \-c
+-.IR class \|]
+-.RB [\| \-t
+-.IR type \|]
+-.RB [\| \-o
+-.IR option : value \]
+-.IR name \|.\|.\|.
+-
+-.SH DESCRIPTION
+-.B dnsget
+-is a simple command-line to perform DNS lookups, similar to
+-.BR host (1)
+-and
+-.BR dig (1).
+-It is useable for both interactive/debugging scenarious and
+-in scripts.
+-The program is implemented using
+-.BR udns (3)
+-library.
+-
+-.PP
+-By default,
+-.B dnsget
+-produces a human-readable output, similar to
+-.RS
+-.nf
+-alias.example.com. CNAME www.example.com.
+-www.example.com. A 192.168.1.1
+-www.example.com. MX 10 mx.example.com.
+-.fi
+-.RE
+-which is just sufficient to see how a given name resolves.
+-Output format is controllable with
+-.B \-v
+-and
+-.B \-q
+-options -- the former increases verbosity level up to printing
+-the whole DNS contents of all packets sent and received, which
+-is suitable for debugging DNS problems, while the latter reduces
+-the level, making output more quiet, up to bare result with no
+-error messages, which is good for scripts.
+-
+-.SH OPTIONS
+-
+-The following options are recognized by
+-.BR dnsget :
+-
+-.TP
+-.B \-v
+-produce more detailed output.  More
+-.BR \-v 's
+-means more details will be produced.  With single
+-.BR \-v , dnsget
+-will print contents of all received DNS packets (in a readable format),
+-while with
+-.BR \-vv ,
+-it will output all outgoing DNS packets too.
+-
+-.TP
+-.B \-q
+-the opposite for \fB\-v\fR -- produce less detailed output.
+-With single
+-.BR \-q , dnsget
+-will only show (decoded) data from final DNS resource records (RR),
+-while
+-.B \-qq
+-also suppresses error messages.
+-
+-.TP
+-\fB\-t \fItype\fR
+-request record(s) of the given type \fItype\fR.  By default,
+-.B dnsget
+-will ask for IPv4 address (A) record, or for PTR record if the
+-argument in question is an IPv4 or IPv6 address.  Recognized
+-types include A, AAAA, MX, TXT, CNAME, PTR, NS, SOA, ANY and
+-others.
+-
+-.TP
+-\fB\-c \fIclass\fR
+-request DNS record(s) of the given class \fIclass\fR.  By
+-default
+-.B dnsget
+-uses IN class.  Valid classes include IN, CH, HS, ANY.
+-
+-.TP
+-.B \-a
+-(compatibility option).  Equivalent to setting query type to
+-.B ANY
+-and increasing verbosity level
+-.RB ( \-v ).
+-
+-.TP
+-.B \-C
+-(planned)
+-
+-.TP
+-.B \-x
+-(planned)
+-
+-.TP
+-\fB\-o \fIoption\fR:\fIvalue\fR
+-Set resolver option \fIoption\fR to the value \fIvalue\fR
+-(may be specified several times).  The same as setting
+-.RB $ RES_OPTIONS
+-environment variable.  The following options are recognized:
+-.RS
+-.TP
+-\fBtimeout\fR:\fIsec\fR
+-Set initial query timeout to \fIsec\fR.
+-.TP
+-\fBattempts\fR:\fInum\fR
+-(re)try every query \fInum\fR times before failing.
+-.TP
+-\fBudpbuf\fR:\fIbytes\fR
+-set DNS UDP buffer size to \fIbytes\fR bytes.  Valid values
+-are from 512 to 65535.  If \fIbytes\fR is greather than 512,
+-EDNS0 (RFC 2671) extensions will be used.
+-.TP
+-\fBport\fR:\fInum\fR
+-Use given UDP port number \fInum\fR instead of the default port 53 (domain).
+-.RE
+-
+-.TP
+-\fB\-n \fInameserver\fR
+-Use the given nameserver(s) (may be specified more than once)
+-instead of the default.  Using this option has the same same effect as 
+-.RB $ NSCACHEIP
+-or
+-.RB $ NAMESERVERS
+-environment variables, with the only difference that only IPv4 addresses
+-are recognized for now, and it is possible to specify names (which will
+-be resolved using default settings) instead of IP addresses.
+-
+-.TP
+-.B \-h
+-print short help and exit.
+-
+-.SH "RETURN VALUE"
+-When all names where resovled successefully,
+-.B dnsget
+-exits with zero exit status.  If at least one name was not found,
+-.B dnsget
+-will exit with return code 100.  If some other error occured during
+-name resolution, it will exit with code 99.  In case of usage or
+-initialization error,
+-.B dnsget
+-will return 1.
+-
+-.SH "SEE ALSO"
+-.BR host (1)
+-.BR dig (1)
+-.BR resolv.conf (5)
+-.BR udns (3).
+diff --git a/udns/source/dnsget.c b/udns/source/dnsget.c
+deleted file mode 100644
+index 1d89a52..0000000
+--- a/udns/source/dnsget.c
++++ /dev/null
+@@ -1,709 +0,0 @@
+-/* $Id: dnsget.c,v 1.22 2006/11/29 21:28:49 mjt Exp $
+-   simple host/dig-like application using UDNS library
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#include <stdio.h>
+-#include <unistd.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <sys/types.h>
+-#include <sys/socket.h>
+-#include <netinet/in.h>
+-#include <arpa/inet.h>
+-#include <time.h>
+-#include <sys/time.h>
+-#include <stdarg.h>
+-#include <errno.h>
+-#include "udns.h"
+-
+-static char *progname;
+-static int verbose = 1;
+-static int errors;
+-static int notfound;
+-
+-/* verbosity level:
+- * <0 - bare result
+- *  0 - bare result and error messages
+- *  1 - readable result
+- *  2 - received packet contents and `trying ...' stuff
+- *  3 - sent and received packet contents
+- */
+-
+-static void die(int errnum, const char *fmt, ...) {
+-  va_list ap;
+-  fprintf(stderr, "%s: ", progname);
+-  va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap);
+-  if (errnum) fprintf(stderr, ": %s\n", strerror(errnum));
+-  else putc('\n', stderr);
+-  fflush(stderr);
+-  exit(1);
+-}
+-
+-struct query {
+-  const char *name;		/* original query string */
+-  unsigned char *dn;		/* the DN being looked up */
+-  enum dns_type qtyp;		/* type of the query */
+-};
+-
+-static void query_free(struct query *q) {
+-  free(q->dn);
+-  free(q);
+-}
+-
+-static struct query *
+-query_new(const char *name, const unsigned char *dn, enum dns_type qtyp) {
+-  struct query *q = malloc(sizeof(*q));
+-  unsigned l = dns_dnlen(dn);
+-  unsigned char *cdn = malloc(l);
+-  if (!q || !cdn) die(0, "out of memory");
+-  memcpy(cdn, dn, l);
+-  q->name = name;
+-  q->dn = cdn;
+-  q->qtyp = qtyp;
+-  return q;
+-}
+-
+-static enum dns_class qcls = DNS_C_IN;
+-
+-static void
+-dnserror(struct query *q, int errnum) {
+-  if (verbose >= 0)
+-    fprintf(stderr, "%s: unable to lookup %s record for %s: %s\n", progname,
+-            dns_typename(q->qtyp), dns_dntosp(q->dn), dns_strerror(errnum));
+-  if (errnum == DNS_E_NXDOMAIN || errnum == DNS_E_NODATA)
+-    ++notfound;
+-  else
+-    ++errors;
+-  query_free(q);
+-}
+-
+-static const unsigned char *
+-printtxt(const unsigned char *c) {
+-  unsigned n = *c++;
+-  const unsigned char *e = c + n;
+-  if (verbose > 0) while(c < e) {
+-    if (*c < ' ' || *c >= 127) printf("\\%02x", *c);
+-    else if (*c == '\\' || *c == '"') printf("\\%c", *c);
+-    else putchar(*c);
+-    ++c;
+-  }
+-  else
+-   fwrite(c, n, 1, stdout);
+-  return e;
+-}
+-
+-static void
+-printhex(const unsigned char *c, const unsigned char *e) {
+-  while(c < e)
+-    printf("%02x", *c++);
+-}
+-
+-static unsigned char to_b64[] =
+-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+-
+-static void
+-printb64(const unsigned char *c, const unsigned char *e) {
+-  while(c < e) {
+-    putchar(to_b64[c[0] >> 2]);
+-    if (c+1 < e) {
+-      putchar(to_b64[(c[0] & 0x3) << 4 | c[1] >> 4]);
+-      if (c+2 < e) {
+-        putchar(to_b64[(c[1] & 0xf) << 2 | c[2] >> 6]);
+-        putchar(to_b64[c[2] & 0x3f]);
+-      }
+-      else {
+-        putchar(to_b64[(c[1] & 0xf) << 2]);
+-	putchar('=');
+-	break;
+-      }
+-    }
+-    else {
+-      putchar(to_b64[(c[0] & 0x3) << 4]);
+-      putchar('=');
+-      putchar('=');
+-      break;
+-    }
+-    c += 3;
+-  }
+-}
+-
+-static void
+-printdate(time_t time) {
+-  struct tm *tm = gmtime(&time);
+-  printf("%04d%02d%02d%02d%02d%02d",
+-    tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+-    tm->tm_hour, tm->tm_min, tm->tm_sec);
+-}
+-
+-static void
+-printrr(const struct dns_parse *p, struct dns_rr *rr) {
+-  const unsigned char *pkt = p->dnsp_pkt;
+-  const unsigned char *end = p->dnsp_end;
+-  const unsigned char *dptr = rr->dnsrr_dptr;
+-  const unsigned char *dend = rr->dnsrr_dend;
+-  unsigned char *dn = rr->dnsrr_dn;
+-  const unsigned char *c;
+-  unsigned n;
+-
+-  if (verbose > 0) {
+-    if (verbose > 1) {
+-      if (!p->dnsp_rrl && !rr->dnsrr_dn[0] && rr->dnsrr_typ == DNS_T_OPT) {
+-        printf(";EDNS0 OPT record (UDPsize: %d): %d bytes\n",
+-               rr->dnsrr_cls, rr->dnsrr_dsz);
+-        return;
+-      }
+-      n = printf("%s.", dns_dntosp(rr->dnsrr_dn));
+-      printf("%s%u\t%s\t%s\t",
+-             n > 15 ? "\t" : n > 7 ? "\t\t" : "\t\t\t",
+-             rr->dnsrr_ttl,
+-             dns_classname(rr->dnsrr_cls),
+-             dns_typename(rr->dnsrr_typ));
+-    }
+-    else
+-      printf("%s. %s ", dns_dntosp(rr->dnsrr_dn), dns_typename(rr->dnsrr_typ));
+-  }
+-
+-  switch(rr->dnsrr_typ) {
+-
+-  case DNS_T_CNAME:
+-  case DNS_T_PTR:
+-  case DNS_T_NS:
+-  case DNS_T_MB:
+-  case DNS_T_MD:
+-  case DNS_T_MF:
+-  case DNS_T_MG:
+-  case DNS_T_MR:
+-    if (dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN) <= 0) goto xperr;
+-    printf("%s.", dns_dntosp(dn));
+-    break;
+-
+-  case DNS_T_A:
+-    if (rr->dnsrr_dsz != 4) goto xperr;
+-    printf("%d.%d.%d.%d", dptr[0], dptr[1], dptr[2], dptr[3]);
+-    break;
+-
+-  case DNS_T_AAAA:
+-    if (rr->dnsrr_dsz != 16) goto xperr;
+-    printf("%s", inet_ntop(AF_INET6, dptr, (char*)dn, DNS_MAXDN));
+-    break;
+-
+-  case DNS_T_MX:
+-    c = dptr + 2;
+-    if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || c != dend) goto xperr;
+-    printf("%d %s.", dns_get16(dptr), dns_dntosp(dn));
+-    break;
+-
+-  case DNS_T_TXT:
+-    /* first verify it */
+-    for(c = dptr; c < dend; c += n) {
+-      n = *c++;
+-      if (c + n > dend) goto xperr;
+-    }
+-    c = dptr; n = 0;
+-    while (c < dend) {
+-      if (verbose > 0) printf(n++ ? "\" \"":"\"");
+-      c = printtxt(c);
+-    }
+-    if (verbose > 0) putchar('"');
+-    break;
+-
+-  case DNS_T_HINFO:	/* CPU, OS */
+-    c = dptr;
+-    n = *c++; if ((c += n) >= dend) goto xperr;
+-    n = *c++; if ((c += n) != dend) goto xperr;
+-    c = dptr;
+-    if (verbose > 0) putchar('"');
+-    c = printtxt(c);
+-    if (verbose > 0) printf("\" \""); else putchar(' ');
+-    printtxt(c);
+-    if (verbose > 0) putchar('"');
+-    break;
+-
+-  case DNS_T_WKS:
+-    c = dptr;
+-    if (dptr + 4 + 2 >= end) goto xperr;
+-    printf("%s %d", inet_ntoa(*((struct in_addr*)dptr)), dptr[4]);
+-    c = dptr + 5;
+-    for (n = 0; c < dend; ++c, n += 8) {
+-      if (*c) {
+-        unsigned b;
+-        for (b = 0; b < 8; ++b)
+-          if (*c & (1 << (7-b))) printf(" %d", n + b);
+-      }
+-    }
+-    break;
+-
+-  case DNS_T_SRV:	/* prio weight port targetDN */
+-    c = dptr;
+-    c += 2 + 2 + 2;
+-    if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || c != dend) goto xperr;
+-    c = dptr;
+-    printf("%d %d %d %s.",
+-           dns_get16(c+0), dns_get16(c+2), dns_get16(c+4),
+-           dns_dntosp(dn));
+-    break;
+-
+-  case DNS_T_NAPTR:	/* order pref flags serv regexp repl */
+-    c = dptr;
+-    c += 4;	/* order, pref */
+-    for (n = 0; n < 3; ++n)
+-      if (c >= dend) goto xperr;
+-      else c += *c + 1;
+-    if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || c != dend) goto xperr;
+-    c = dptr;
+-    printf("%u %u", dns_get16(c+0), dns_get16(c+2));
+-    c += 4;
+-    for(n = 0; n < 3; ++n) {
+-      putchar(' ');
+-      if (verbose > 0) putchar('"');
+-      c = printtxt(c);
+-      if (verbose > 0) putchar('"');
+-    } 
+-    printf(" %s.", dns_dntosp(dn));
+-    break;
+-
+-  case DNS_T_KEY: /* flags(2) proto(1) algo(1) pubkey */
+-    c = dptr;
+-    if (c + 2 + 1 + 1 > dend) goto xperr;
+-    printf("%d %d %d", dns_get16(c), c[2], c[3]);
+-    c += 2 + 1 + 1;
+-    if (c < dend) {
+-      putchar(' ');
+-      printb64(c, dend);
+-    }
+-    break;
+-
+-  case DNS_T_SIG:
+-    /* type(2) algo(1) labels(1) ottl(4) sexp(4) sinc(4) tag(2) sdn sig */
+-    c = dptr;
+-    c += 2 + 1 + 1 + 4 + 4 + 4 + 2;
+-    if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0) goto xperr;
+-    printf("%d %u %u %u ",
+-           dns_get16(dptr), dptr[2], dptr[3], dns_get32(dptr+4));
+-    printdate(dns_get32(dptr+8));
+-    putchar(' ');
+-    printdate(dns_get32(dptr+12));
+-    printf(" %d %s. ", dns_get16(dptr+10), dns_dntosp(dn));
+-    printb64(c, dend);
+-    break;
+-
+-#if 0	/* unused RR types? */
+-  case DNS_T_DS:
+-    c = dptr;
+-    if (c + 2 + 2 >= dend) goto xperr;
+-    printf("%u %u %u ", dns_get16(c), c[2], c[3]);
+-    printhex(c + 4, dend);
+-    break;
+-
+-  case DNS_T_NSEC:
+-    c = dptr;
+-    if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0) goto xperr;
+-    printf("%s.", dns_dntosp(dn));
+-    unfinished.
+-    break;
+-#endif
+-
+-
+-  case DNS_T_SOA:
+-    c = dptr;
+-    if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 ||
+-        dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 ||
+-        c + 4*5 != dend)
+-      goto xperr;
+-    dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN);
+-    printf("%s. ", dns_dntosp(dn));
+-    dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN);
+-    printf("%s. ", dns_dntosp(dn));
+-    printf("%u %u %u %u %u",
+-           dns_get32(dptr), dns_get32(dptr+4), dns_get32(dptr+8),
+-           dns_get32(dptr+12), dns_get32(dptr+16));
+-    break;
+-
+-  case DNS_T_MINFO:
+-    c = dptr;
+-    if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 ||
+-        dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 ||
+-	c != dend)
+-      goto xperr;
+-    dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN);
+-    printf("%s. ", dns_dntosp(dn));
+-    dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN);
+-    printf("%s.", dns_dntosp(dn));
+-    break;
+-
+-  case DNS_T_NULL:
+-  default:
+-    printhex(dptr, dend);
+-    break;
+-  }
+-  putchar('\n');
+-  return;
+-
+-xperr:
+-  printf("<parse error>\n");
+-  ++errors;
+-}
+-
+-static int
+-printsection(struct dns_parse *p, int nrr, const char *sname) {
+-  struct dns_rr rr;
+-  int r;
+-  if (!nrr) return 0;
+-  if (verbose > 1) printf("\n;; %s section (%d):\n", sname, nrr);
+-
+-  p->dnsp_rrl = nrr;
+-  while((r = dns_nextrr(p, &rr)) > 0)
+-    printrr(p, &rr);
+-  if (r < 0) printf("<<ERROR>>\n");
+-  return r;
+-}
+-
+-/* dbgcb will only be called if verbose > 1 */
+-static void
+-dbgcb(int code, const struct sockaddr *sa, unsigned slen,
+-      const unsigned char *pkt, int r,
+-      const struct dns_query *unused_q, void *unused_data) {
+-  struct dns_parse p;
+-  const unsigned char *cur, *end;
+-  int numqd;
+-
+-  if (code > 0)	{
+-    printf(";; trying %s.\n", dns_dntosp(dns_payload(pkt)));
+-    printf(";; sending %d bytes query to ", r);
+-  }
+-  else
+-    printf(";; received %d bytes response from ", r);
+-  if (sa->sa_family == AF_INET && slen >= sizeof(struct sockaddr_in)) {
+-    char buf[4*4];
+-    printf("%s port %d\n",
+-           inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr,
+-                     buf, sizeof(buf)),
+-           htons(((struct sockaddr_in*)sa)->sin_port));
+-  }
+-#ifdef AF_INET6
+-  else if (sa->sa_family == AF_INET6 && slen >= sizeof(struct sockaddr_in6)) {
+-    char buf[6*5+4*4];
+-    printf("%s port %d\n",
+-           inet_ntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr,
+-                     buf, sizeof(buf)),
+-           htons(((struct sockaddr_in6*)sa)->sin6_port));
+-  }
+-#endif
+-  else
+-    printf("<<unknown socket type %d>>\n", sa->sa_family);
+-  if (code > 0 && verbose < 3) {
+-    putchar('\n');
+-    return;
+-  }
+-
+-  if (code == -2) printf(";; reply from unexpected source\n");
+-  if (code == -5) printf(";; reply to a query we didn't sent (or old)\n");
+-  if (r < DNS_HSIZE) {
+-    printf(";; short packet (%d bytes)\n", r);
+-    return;
+-  }
+-  if (dns_opcode(pkt) != 0)
+-    printf(";; unexpected opcode %d\n", dns_opcode(pkt));
+-  if (dns_tc(pkt) != 0)
+-    printf(";; warning: TC bit set, probably incomplete reply\n");
+-
+-  printf(";; ->>HEADER<<- opcode: ");
+-  switch(dns_opcode(pkt)) {
+-  case 0: printf("QUERY"); break;
+-  case 1: printf("IQUERY"); break;
+-  case 2: printf("STATUS"); break;
+-  default: printf("UNKNOWN(%u)", dns_opcode(pkt)); break;
+-  }
+-  printf(", status: %s, id: %d, size: %d\n;; flags:",
+-         dns_rcodename(dns_rcode(pkt)), dns_qid(pkt), r);
+-  if (dns_qr(pkt)) printf(" qr");
+-  if (dns_rd(pkt)) printf(" rd");
+-  if (dns_ra(pkt)) printf(" ra");
+-  if (dns_aa(pkt)) printf(" aa");
+-  if (dns_tc(pkt)) printf(" tc");
+-  numqd = dns_numqd(pkt);
+-  printf("; QUERY: %d, ANSWER: %d, AUTHORITY: %d, ADDITIONAL: %d\n",
+-         numqd, dns_numan(pkt), dns_numns(pkt), dns_numar(pkt));
+-  if (numqd != 1)
+-    printf(";; unexpected number of entries in QUERY section: %d\n",
+-           numqd);
+-  printf("\n;; QUERY SECTION (%d):\n", numqd);
+-  cur = dns_payload(pkt);
+-  end = pkt + r;
+-  while(numqd--) {
+-    if (dns_getdn(pkt, &cur, end, p.dnsp_dnbuf, DNS_MAXDN) <= 0 ||
+-        cur + 4 > end) {
+-      printf("; invalid query section\n");
+-      return;
+-    }
+-    r = printf(";%s.", dns_dntosp(p.dnsp_dnbuf));
+-    printf("%s%s\t%s\n",
+-           r > 23 ? "\t" : r > 15 ? "\t\t" : r > 7 ? "\t\t\t" : "\t\t\t\t",
+-           dns_classname(dns_get16(cur+2)), dns_typename(dns_get16(cur)));
+-    cur += 4;
+-  }
+-
+-  p.dnsp_pkt = pkt;
+-  p.dnsp_cur = p.dnsp_ans = cur;
+-  p.dnsp_end = end;
+-  p.dnsp_qdn = NULL;
+-  p.dnsp_qcls = p.dnsp_qtyp = 0;
+-  p.dnsp_ttl = 0xffffffffu;
+-  p.dnsp_nrr = 0;
+-
+-  r = printsection(&p, dns_numan(pkt), "ANSWER");
+-  if (r == 0)
+-    r = printsection(&p, dns_numns(pkt), "AUTHORITY");
+-  if (r == 0)
+-    r = printsection(&p, dns_numar(pkt), "ADDITIONAL");
+-  putchar('\n');
+-}
+-
+-static void dnscb(struct dns_ctx *ctx, void *result, void *data) {
+-  int r = dns_status(ctx);
+-  struct query *q = data;
+-  struct dns_parse p;
+-  struct dns_rr rr;
+-  unsigned nrr;
+-  unsigned char dn[DNS_MAXDN];
+-  const unsigned char *pkt, *cur, *end;
+-  if (!result) {
+-    dnserror(q, r);
+-    return;
+-  }
+-  pkt = result; end = pkt + r; cur = dns_payload(pkt);
+-  dns_getdn(pkt, &cur, end, dn, sizeof(dn));
+-  dns_initparse(&p, NULL, pkt, cur, end);
+-  p.dnsp_qcls = p.dnsp_qtyp = 0;
+-  nrr = 0;
+-  while((r = dns_nextrr(&p, &rr)) > 0) {
+-    if (!dns_dnequal(dn, rr.dnsrr_dn)) continue;
+-    if ((qcls == DNS_C_ANY || qcls == rr.dnsrr_cls) &&
+-        (q->qtyp == DNS_T_ANY || q->qtyp == rr.dnsrr_typ))
+-      ++nrr;
+-    else if (rr.dnsrr_typ == DNS_T_CNAME && !nrr) {
+-      if (dns_getdn(pkt, &rr.dnsrr_dptr, end,
+-                    p.dnsp_dnbuf, sizeof(p.dnsp_dnbuf)) <= 0 ||
+-          rr.dnsrr_dptr != rr.dnsrr_dend) {
+-        r = DNS_E_PROTOCOL;
+-        break;
+-      }
+-      else {
+-        if (verbose == 1) {
+-          printf("%s.", dns_dntosp(dn));
+-          printf(" CNAME %s.\n", dns_dntosp(p.dnsp_dnbuf));
+-        }
+-	dns_dntodn(p.dnsp_dnbuf, dn, sizeof(dn));
+-      }
+-    }
+-  }
+-  if (!r && !nrr)
+-    r = DNS_E_NODATA;
+-  if (r < 0) {
+-    dnserror(q, r);
+-    free(result);
+-    return;
+-  }
+-  if (verbose < 2) {	/* else it is already printed by dbgfn */
+-    dns_rewind(&p, NULL);
+-    p.dnsp_qtyp = q->qtyp;
+-    p.dnsp_qcls = qcls;
+-    while(dns_nextrr(&p, &rr))
+-      printrr(&p, &rr);
+-  }
+-  free(result);
+-  query_free(q);
+-}
+-
+-int main(int argc, char **argv) {
+-  int i;
+-  int fd;
+-  fd_set fds;
+-  struct timeval tv;
+-  time_t now;
+-  char *ns[DNS_MAXSERV];
+-  int nns = 0;
+-  struct query *q;
+-  enum dns_type qtyp = 0;
+-  struct dns_ctx *nctx = NULL;
+-
+-  if (!(progname = strrchr(argv[0], '/'))) progname = argv[0];
+-  else argv[0] = ++progname;
+-
+-  if (argc <= 1)
+-    die(0, "try `%s -h' for help", progname);
+-
+-  if (dns_init(0) < 0 || !(nctx = dns_new(NULL)))
+-    die(errno, "unable to initialize dns library");
+-  /* we keep two dns contexts: one may be needed to resolve
+-   * nameservers if given as names, using default options.
+-   */
+-
+-  while((i = getopt(argc, argv, "vqt:c:an:o:h")) != EOF) switch(i) {
+-  case 'v': ++verbose; break;
+-  case 'q': --verbose; break;
+-  case 't':
+-    if (optarg[0] == '*' && !optarg[1])
+-      i = DNS_T_ANY;
+-    else if ((i = dns_findtypename(optarg)) <= 0)
+-      die(0, "unrecognized query type `%s'", optarg);
+-    qtyp = i;
+-    break;
+-  case 'c':
+-    if (optarg[0] == '*' && !optarg[1])
+-      i = DNS_C_ANY;
+-    else if ((i = dns_findclassname(optarg)) < 0)
+-      die(0, "unrecognized query class `%s'", optarg);
+-    qcls = i;
+-    break;
+-  case 'a':
+-    qtyp = DNS_T_ANY;
+-    ++verbose;
+-    break;
+-  case 'n':
+-    if (nns >= DNS_MAXSERV)
+-      die(0, "too many nameservers, %d max", DNS_MAXSERV);
+-    ns[nns++] = optarg;
+-    break;
+-  case 'o':
+-    if (dns_set_opts(NULL, optarg) != 0)
+-      die(0, "invalid option string: `%s'", optarg);
+-    break;
+-  case 'h':
+-    printf(
+-"%s: simple DNS query tool (using udns version %s)\n"
+-"Usage: %s [options] domain-name...\n"
+-"where options are:\n"
+-" -h - print this help and exit\n"
+-" -v - be more verbose\n"
+-" -q - be less verbose\n"
+-" -t type - set query type (A, AA, PTR etc)\n"
+-" -c class - set query class (IN (default), CH, HS, *)\n"
+-" -a - equivalent to -t ANY -v\n"
+-" -n ns - use given nameserver(s) instead of default\n"
+-"  (may be specified multiple times)\n"
+-" -o option:value - set resovler option (the same as setting $RES_OPTIONS):\n"
+-"  timeout:sec  - initial query timeout\n"
+-"  attempts:num - number of attempt to resovle a query\n"
+-"  ndots:num    - if name has more than num dots, lookup it before search\n"
+-"  port:num     - port number for queries instead of default 53\n"
+-"  udpbuf:num   - size of UDP buffer (use EDNS0 if >512)\n"
+-"  (may be specified more than once)\n"
+-      , progname, dns_version(), progname);
+-    return 0;
+-  default:
+-    die(0, "try `%s -h' for help", progname);
+-  }
+-
+-  argc -= optind; argv += optind;
+-  if (!argc)
+-    die(0, "no name(s) to query specified");
+-
+-  if (nns) {
+-    /* if nameservers given as names, resolve them.
+-     * We only allow IPv4 nameservers as names for now.
+-     * Ok, it is easy enouth to try both AAAA and A,
+-     * but the question is what to do by default.
+-     */
+-    struct sockaddr_in sin;
+-    int j, r = 0, opened = 0;
+-    memset(&sin, 0, sizeof(sin));
+-    sin.sin_family = AF_INET;
+-    sin.sin_port = htons(dns_set_opt(NULL, DNS_OPT_PORT, -1));
+-    dns_add_serv(NULL, NULL);
+-    for(i = 0; i < nns; ++i) {
+-      if (!inet_aton(ns[i], &sin.sin_addr)) {
+-        struct dns_rr_a4 *rr;
+-        if (!opened) {
+-          if (dns_open(nctx) < 0)
+-            die(errno, "unable to initialize dns context");
+-          opened = 1;
+-        }
+-        rr = dns_resolve_a4(nctx, ns[i], 0);
+-        if (!rr)
+-          die(0, "unable to resolve nameserver %s: %s",
+-              ns[i], dns_strerror(dns_status(nctx)));
+-        for(j = 0; j < rr->dnsa4_nrr; ++j) {
+-          sin.sin_addr = rr->dnsa4_addr[j];
+-          if ((r = dns_add_serv_s(NULL, (struct sockaddr *)&sin)) < 0)
+-            break;
+-        }
+-        free(rr);
+-      }
+-      else
+-        r = dns_add_serv_s(NULL, (struct sockaddr *)&sin);
+-      if (r < 0)
+-        die(errno, "unable to add nameserver %s", inet_ntoa(sin.sin_addr));
+-    }
+-  }
+-  dns_free(nctx);
+-
+-  fd = dns_open(NULL);
+-  if (fd < 0)
+-    die(errno, "unable to initialize dns context");
+-
+-  if (verbose > 1)
+-    dns_set_dbgfn(NULL, dbgcb);
+-
+-  for (i = 0; i < argc; ++i) {
+-    char *name = argv[i];
+-    union {
+-      struct in_addr addr;
+-      struct in6_addr addr6;
+-    } a;
+-    unsigned char dn[DNS_MAXDN];
+-    enum dns_type l_qtyp = 0;
+-    int abs;
+-    if (inet_pton(AF_INET, name, &a.addr) > 0) {
+-      dns_a4todn(&a.addr, 0, dn, sizeof(dn));
+-      l_qtyp = DNS_T_PTR;
+-      abs = 1;
+-    }
+-    else if (inet_pton(AF_INET6, name, &a.addr6) > 0) {
+-      dns_a6todn(&a.addr6, 0, dn, sizeof(dn));
+-      l_qtyp = DNS_T_PTR;
+-      abs = 1;
+-    }
+-    else if (!dns_ptodn(name, strlen(name), dn, sizeof(dn), &abs))
+-      die(0, "invalid name `%s'\n", name);
+-    else
+-      l_qtyp = DNS_T_A;
+-    if (qtyp) l_qtyp = qtyp;
+-    q = query_new(name, dn, l_qtyp);
+-    if (abs) abs = DNS_NOSRCH;
+-    if (!dns_submit_dn(NULL, dn, qcls, l_qtyp, abs, 0, dnscb, q))
+-      dnserror(q, dns_status(NULL));
+-  }
+-
+-  FD_ZERO(&fds);
+-  now = 0;
+-  while((i = dns_timeouts(NULL, -1, now)) > 0) {
+-    FD_SET(fd, &fds);
+-    tv.tv_sec = i;
+-    tv.tv_usec = 0;
+-    i = select(fd+1, &fds, 0, 0, &tv);
+-    now = time(NULL);
+-    if (i > 0) dns_ioevent(NULL, now);
+-  }
+-
+-  return errors ? 1 : notfound ? 100 : 0;
+-}
+diff --git a/udns/source/ex-rdns.c b/udns/source/ex-rdns.c
+deleted file mode 100644
+index bc705c7..0000000
+--- a/udns/source/ex-rdns.c
++++ /dev/null
+@@ -1,111 +0,0 @@
+-/* $Id: ex-rdns.c,v 1.6 2005/05/07 12:21:42 mjt Exp $
+-   parallel rDNS resolver example - read IP addresses from stdin,
+-   write domain names to stdout
+- 
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#include <sys/types.h>
+-#include <sys/socket.h>
+-#include <netinet/in.h>
+-#include <arpa/inet.h>
+-#include <sys/poll.h>
+-#include <unistd.h>
+-#include <stdio.h>
+-#include <time.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include "udns.h"
+-
+-static int curq;
+-
+-static const char *n2ip(const unsigned char *c) {
+-  static char b[sizeof("255.255.255.255")];
+-  sprintf(b, "%u.%u.%u.%u", c[0], c[1], c[2], c[3]);
+-  return b;
+-}
+-static void dnscb(struct dns_ctx *ctx, struct dns_rr_ptr *rr, void *data) {
+-  const char *ip = n2ip((unsigned char *)&data);
+-  int i;
+-  --curq;
+-  if (rr) {
+-    printf("%s", ip);
+-    for(i = 0; i < rr->dnsptr_nrr; ++i)
+-      printf(" %s", rr->dnsptr_ptr[i]);
+-    putchar('\n');
+-    free(rr);
+-  }
+-  else
+-    fprintf(stderr, "%s: %s\n", ip, dns_strerror(dns_status(ctx)));
+-}
+-
+-int main(int argc, char **argv) {
+-  int c, t;
+-  time_t now;
+-  int maxq = 10;
+-  struct pollfd pfd;
+-  char linebuf[1024];
+-  char *eol;
+-  int eof;
+-
+-  if (dns_init(1) < 0) return 1;
+-  while((c = getopt(argc, argv, "m:r")) != EOF) switch(c) {
+-  case 'm': maxq = atoi(optarg); break;
+-  case 'r':
+-     dns_set_opt(0, DNS_OPT_FLAGS,
+-                 dns_set_opt(0, DNS_OPT_FLAGS, -1) | DNS_NORD);
+-     break;
+-  default: return 1;
+-  }
+-  if (argc != optind) return 1;
+-
+-  pfd.fd = dns_sock(0);
+-  pfd.events = POLLIN;
+-  now = time(NULL);
+-  c = optind;
+-  eof = 0;
+-  while(curq || !eof) {
+-    if (!eof && curq < maxq) {
+-      union { struct in_addr a; void *p; } pa;
+-      if (!fgets(linebuf, sizeof(linebuf), stdin)) {
+-        eof = 1;
+-        continue;
+-      }
+-      eol = strchr(linebuf, '\n');
+-      if (eol) *eol = '\0';
+-      if (!linebuf[0]) continue;
+-      if (!inet_aton(linebuf, &pa.a))
+-        fprintf(stderr, "%s: invalid address\n", linebuf);
+-      else if (dns_submit_a4ptr(0, &pa.a, dnscb, pa.p) == 0)
+-        fprintf(stderr, "%s: unable to submit query: %s\n",
+-                linebuf, dns_strerror(dns_status(0)));
+-      else
+-        ++curq;
+-      continue;
+-    }
+-    if (curq) {
+-      t = dns_timeouts(0, -1, now);
+-      t = poll(&pfd, 1, c * 1000);
+-      now = time(NULL);
+-      if (t) dns_ioevent(0, now);
+-    }
+-  }
+-  return 0;
+-}
+diff --git a/udns/source/rblcheck.1 b/udns/source/rblcheck.1
+deleted file mode 100644
+index 0e427e4..0000000
+--- a/udns/source/rblcheck.1
++++ /dev/null
+@@ -1,151 +0,0 @@
+-.\" $Id: rblcheck.1,v 1.1 2005/04/24 23:14:23 mjt Exp $
+-.\" rblckeck manpage
+-.\"
+-.\" Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-.\" This file is part of UDNS library, an async DNS stub resolver.
+-.\"
+-.\" This library is free software; you can redistribute it and/or
+-.\" modify it under the terms of the GNU Lesser General Public
+-.\" License as published by the Free Software Foundation; either
+-.\" version 2.1 of the License, or (at your option) any later version.
+-.\"
+-.\" This library 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
+-.\" Lesser General Public License for more details.
+-.\"
+-.\" You should have received a copy of the GNU Lesser General Public
+-.\" License along with this library, in file named COPYING.LGPL; if not,
+-.\" write to the Free Software Foundation, Inc., 59 Temple Place,
+-.\" Suite 330, Boston, MA  02111-1307  USA
+-
+-.TH rblckeck 1 "Apr 2005" "User Utilities"
+-
+-.SH NAME
+-rblckeck \- DNSBL lookup utility
+-
+-.SH SYNOPSYS
+-.B rblcheck
+-.RB [\| \-s
+-.IR zone \|]
+-.RB [\| \-S
+-.IR zone\-file \|]
+-.RB [\| \-c \|]
+-.RB [\| \-tmvq \|]
+-.RB [\| \-n
+-.IR nsaddr \|]
+-.IR address \|.\|.\|.
+-
+-.SH DESCRIPTION
+-.B rblcheck
+-is a simple command-line to perform DNSBL (DNS-based blocklists) lookups.
+-For every IP address (or a name, in which case it will be resolved to an
+-address first), the utility verifies whenever it is listed in a (list of)
+-DNS blocklists specified with
+-.B \-s
+-or
+-.B \-S
+-options, optionally obtains text assotiated with the listing (usually it
+-is either some description about the reason of the listing or an URL
+-referring to such a description), and displays results on standard output.
+-.PP
+-The program is implemented on top of
+-.BR udns (3)
+-library.
+-
+-.SH OPTIONS
+-
+-The following options are recognized by
+-.BR rblcheck :
+-
+-.TP
+-.B \-s \fIzone\fR
+-add the given \fIzone\fR DNSBL name to the list of active zones.
+-.TP
+-.B \-S \fIzone-file\fR
+-add list of zones from the named \fIzone-file\fR to the list of
+-active zones (the file specifies one zone as the first word on a
+-line, empty lines and lines starting with `#' character are ignored).
+-.TP
+-.B \-c
+-reset active zone list.
+-.TP
+-.B \-v
+-be more verbose, produce more detailed output.
+-.TP
+-.B \-q
+-the opposite for \fB\-v\fR -- produce less detailed output.
+-.TP
+-.B \-t
+-obtain text for listed addresses.
+-.TP
+-.B \-n \fInsaddr\fR
+-Use the given nameserver (given as IPv4 or IPv6 address) instead of the
+-default.  The same effect may be achieved by setting $NSCACHEIP environment
+-variable.
+-.TP
+-.B \-m
+-stop after first hit, ie after the first address which is found to be
+-listed.
+-
+-.TP
+-.B \-h
+-print short help and exit.
+-
+-.PP
+-If no
+-.BR \-s ,
+-.BR \-S
+-and
+-.B \-c
+-options are given,
+-.B rblcheck
+-will try to obtain list of zones using $RBLCHECK_ZONES environment variable,
+-or ~/.rblcheckrc, or /etc/rblckechrc files, in that order.  If no zones are
+-found, it will exit unsuccessefully.
+-
+-.SH "RETURN VALUE"
+-When no addresses given are listed and no errors occured,
+-.B rblcheck
+-exits with code 0.  If at least one address is listed,
+-.B rblcheck
+-returns 100.  In case of DNS errors,
+-.B rblcheck
+-returns 2.
+-
+-.SH ENVIRONMENT
+-
+-.TP
+-.B $RBLCHECK_ZONES
+-if no
+-.BR \-s ,
+-.B \-S
+-or
+-.B \-c
+-option is given,
+-.B rblcheck
+-tries this variable to obtain list of DNSBL zones to check against.
+-
+-.SH FILES
+-
+-.TP
+-$HOME/.rblcheckrc and /etc/rblcheckrc
+-if no
+-.BR \-s ,
+-.B \-S
+-or
+-.B \-c
+-option is given, and no $RBLCHECK_ZONES environment variable is set,
+-.B rblcheck
+-will try the two files (the first one that exists) to obtain list of
+-DNSBL zones to check against.
+-Each line specifies one zone (only first word in each line is used).
+-Empty lines and lines starting with `#' character are ignored.
+-
+-.SH "SEE ALSO"
+-.BR dnsget (1)
+-.BR resolv.conf (5)
+-.BR udns (3).
+-
+-.SH AUTHOR
+-This program and manual pages are written by Michael Tokarev.
+diff --git a/udns/source/rblcheck.c b/udns/source/rblcheck.c
+deleted file mode 100644
+index 77bc1bf..0000000
+--- a/udns/source/rblcheck.c
++++ /dev/null
+@@ -1,364 +0,0 @@
+-/* $Id: rblcheck.c,v 1.9 2005/04/24 22:49:10 mjt Exp $
+-   dnsbl (rbl) checker application
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <unistd.h>
+-#include <string.h>
+-#include <sys/types.h>
+-#include <sys/socket.h>
+-#include <netinet/in.h>
+-#include <arpa/inet.h>
+-#include <time.h>
+-#include <sys/time.h>
+-#include <errno.h>
+-#include "udns.h"
+-
+-static const char *version = "udns-rblcheck 0.1";
+-static char *progname;
+-
+-struct rblookup {
+-  struct ipcheck *parent;
+-  struct in_addr key;
+-  const char *zone;
+-  struct dns_rr_a4  *addr;
+-  struct dns_rr_txt *txt;
+-};
+-
+-struct ipcheck {
+-  const char *name;
+-  int naddr;
+-  int listed;
+-  struct rblookup *lookup;
+-};
+-
+-#define notlisted ((void*)1)
+-
+-static int nzones, nzalloc;
+-static const char **zones;
+-
+-static int do_txt;
+-static int stopfirst;
+-static int verbose = 1;
+-/* verbosity level:
+- * <0 - only bare As/TXTs
+- * 0 - what RBL result
+- * 1(default) - what is listed by RBL: result
+- * 2          - what is[not ]listed by RBL: result, name lookups
+- */
+-
+-static int listed;
+-static int failures;
+-
+-static void *ecalloc(int size, int cnt) {
+-  void *t = calloc(size, cnt);
+-  if (!t) {
+-    fprintf(stderr, "%s: out of memory\n", progname);
+-    exit(1);
+-  }
+-  return t;
+-}
+-
+-static void addzone(const char *zone) {
+-  if (nzones >= nzalloc) {
+-    const char **zs = (const char**)ecalloc(sizeof(char*), (nzalloc += 16));
+-    if (zones) {
+-      memcpy(zs, zones, nzones * sizeof(char*));
+-      free(zones);
+-    }
+-    zones = zs;
+-  }
+-  zones[nzones++] = zone;
+-}
+-
+-static int addzonefile(const char *fname) {
+-  FILE *f = fopen(fname, "r");
+-  char linebuf[2048];
+-  if (!f)
+-    return 0;
+-  while(fgets(linebuf, sizeof(linebuf), f)) {
+-    char *p = linebuf, *e;
+-    while(*p == ' ' || *p == '\t') ++p;
+-    if (*p == '#' || *p == '\n') continue;
+-    e = p;
+-    while(*e && *e != ' ' && *e != '\t' && *e != '\n')
+-      ++e;
+-    *e = '\0';
+-    addzone(p);
+-  }
+-  fclose(f);
+-  return 1;
+-}
+-
+-static void dnserror(struct rblookup *ipl, const char *what) {
+-  fprintf(stderr, "%s: unable to %s for %s (%s): %s\n",
+-          progname, what, inet_ntoa(ipl->key), ipl->zone,
+-          dns_strerror(dns_status(0)));
+-  ++failures;
+-}
+-
+-static void display_result(struct ipcheck *ipc) {
+-  int j;
+-  struct rblookup *l, *le;
+-  if (!ipc->naddr) return;
+-  for (l = ipc->lookup, le = l + nzones * ipc->naddr; l < le; ++l) {
+-    if (!l->addr) continue;
+-    if (verbose < 2 && l->addr == notlisted) continue;
+-    if (verbose >= 0) {
+-      if (ipc->name) printf("%s[%s]", ipc->name, inet_ntoa(l->key));
+-      else printf("%s", inet_ntoa(l->key));
+-    }
+-    if (l->addr == notlisted) {
+-      printf(" is NOT listed by %s\n", l->zone);
+-      continue;
+-    }
+-    else if (verbose >= 1)
+-      printf(" is listed by %s: ", l->zone);
+-    else if (verbose >= 0)
+-      printf(" %s ", l->zone);
+-    if (verbose >= 1 || !do_txt)
+-      for (j = 0; j < l->addr->dnsa4_nrr; ++j)
+-        printf("%s%s", j ? " " : "", inet_ntoa(l->addr->dnsa4_addr[j]));
+-    if (!do_txt) ;
+-    else if (l->txt) {
+-      for(j = 0; j < l->txt->dnstxt_nrr; ++j) {
+-        unsigned char *t = l->txt->dnstxt_txt[j].txt;
+-        unsigned char *e = t + l->txt->dnstxt_txt[j].len;
+-        printf("%s\"", verbose > 0 ? "\n\t" : j ? " " : "");
+-        while(t < e) {
+-          if (*t < ' ' || *t >= 127) printf("\\x%02x", *t);
+-          else if (*t == '\\' || *t == '"') printf("\\%c", *t);
+-          else putchar(*t);
+-          ++t;
+-        }
+-        putchar('"');
+-      }
+-      free(l->txt);
+-    }
+-    else
+-      printf("%s<no text available>", verbose > 0 ? "\n\t" : "");
+-    free(l->addr);
+-    putchar('\n');
+-  }
+-  free(ipc->lookup);
+-}
+-
+-static void txtcb(struct dns_ctx *ctx, struct dns_rr_txt *r, void *data) {
+-  struct rblookup *ipl = data;
+-  if (r) {
+-    ipl->txt = r;
+-    ++ipl->parent->listed;
+-  }
+-  else if (dns_status(ctx) != DNS_E_NXDOMAIN)
+-    dnserror(ipl, "lookup DNSBL TXT record");
+-}
+-
+-static void a4cb(struct dns_ctx *ctx, struct dns_rr_a4 *r, void *data) {
+-  struct rblookup *ipl = data;
+-  if (r) {
+-    ipl->addr = r;
+-    ++listed;
+-    if (do_txt) {
+-      if (dns_submit_a4dnsbl_txt(0, &ipl->key, ipl->zone, txtcb, ipl))
+-        return;
+-      dnserror(ipl, "submit DNSBL TXT record");
+-    }
+-    ++ipl->parent->listed;
+-  }
+-  else if (dns_status(ctx) != DNS_E_NXDOMAIN)
+-    dnserror(ipl, "lookup DNSBL A record");
+-  else
+-    ipl->addr = notlisted;
+-}
+-
+-static int
+-submit_a_queries(struct ipcheck *ipc,
+-                 int naddr, const struct in_addr *addr) {
+-  int z, a;
+-  struct rblookup *rl = ecalloc(sizeof(*rl), nzones * naddr);
+-  ipc->lookup = rl;
+-  ipc->naddr = naddr;
+-  for(a = 0; a < naddr; ++a) {
+-    for(z = 0; z < nzones; ++z) {
+-      rl->key = addr[a];
+-      rl->zone = zones[z];
+-      rl->parent = ipc;
+-      if (!dns_submit_a4dnsbl(0, &rl->key, rl->zone, a4cb, rl))
+-        dnserror(rl, "submit DNSBL A query");
+-      ++rl;
+-    }
+-  }
+-  return 0;
+-}
+-
+-static void namecb(struct dns_ctx *ctx, struct dns_rr_a4 *rr, void *data) {
+-  struct ipcheck *ipc = data;
+-  if (rr) {
+-    submit_a_queries(ipc, rr->dnsa4_nrr, rr->dnsa4_addr);
+-    free(rr);
+-  }
+-  else
+-    fprintf(stderr, "%s: unable to lookup %s: %s\n",
+-            progname, ipc->name, dns_strerror(dns_status(ctx)));
+-}
+-
+-static int submit(struct ipcheck *ipc) {
+-  struct in_addr addr;
+-  if (inet_aton(ipc->name, &addr)) {
+-    submit_a_queries(ipc, 1, &addr);
+-    ipc->name = NULL;
+-  }
+-  else if (!dns_submit_a4(0, ipc->name, 0, namecb, ipc))
+-    fprintf(stderr, "%s: unable to submit name query for %s: %s\n",
+-            progname, ipc->name, dns_strerror(dns_status(0)));
+-  return 0;
+-}
+-
+-static void waitdns(struct ipcheck *ipc) {
+-  struct timeval tv;
+-  fd_set fds;
+-  int c;
+-  int fd = dns_sock(NULL);
+-  time_t now = 0;
+-  FD_ZERO(&fds);
+-  while((c = dns_timeouts(NULL, -1, now)) > 0) {
+-    FD_SET(fd, &fds);
+-    tv.tv_sec = c;
+-    tv.tv_usec = 0;
+-    c = select(fd+1, &fds, NULL, NULL, &tv);
+-    now = time(NULL);
+-    if (c > 0)
+-      dns_ioevent(NULL, now);
+-    if (stopfirst && ipc->listed)
+-      break;
+-  }
+-}
+-
+-int main(int argc, char **argv) {
+-  int c;
+-  struct ipcheck ipc;
+-  char *nameserver = NULL;
+-  int zgiven = 0;
+-
+-  if (!(progname = strrchr(argv[0], '/'))) progname = argv[0];
+-  else argv[0] = ++progname;
+-
+-  while((c = getopt(argc, argv, "hqtvms:S:cn:")) != EOF) switch(c) {
+-  case 's': ++zgiven; addzone(optarg); break;
+-  case 'S':
+-    ++zgiven;
+-    if (addzonefile(optarg)) break;
+-    fprintf(stderr, "%s: unable to read %s\n", progname, optarg);
+-    return 1;
+-  case 'c': ++zgiven; nzones = 0; break;
+-  case 'q': --verbose; break;
+-  case 'v': ++verbose; break;
+-  case 't': do_txt = 1; break;
+-  case 'n': nameserver = optarg; break;
+-  case 'm': ++stopfirst; break;
+-  case 'h':
+-    printf("%s: %s.\n", progname, version);
+-    printf("Usage is: %s [options] address..\n", progname);
+-    printf(
+-"Where options are:\n"
+-" -h - print this help and exit\n"
+-" -s service - add the service (DNSBL zone) to the serice list\n"
+-" -S service-file - add the DNSBL zone(s) read from the given file\n"
+-" -c - clear service list\n"
+-" -v - increase verbosity level (more -vs => more verbose)\n"
+-" -q - decrease verbosity level (opposite of -v)\n"
+-" -t - obtain and print TXT records if any\n"
+-" -m - stop checking after first address match in any list\n"
+-" -n ipaddr - use the given nameserver instead of the default\n"
+-"(if no -s or -S option is given, use $RBLCHECK_ZONES, ~/.rblcheckrc\n"
+-"or /etc/rblcheckrc in that order)\n"
+-    );
+-    return 0;
+-  default:
+-    fprintf(stderr, "%s: use `%s -h' for help\n", progname, progname);
+-    return 1;
+-  }
+-
+-  if (!zgiven) {
+-    char *s = getenv("RBLCHECK_ZONES");
+-    if (s) {
+-      char *k;
+-      s = strdup(s);
+-      k = strtok(s, " \t");
+-      while(k) {
+-        addzone(k);
+-        k = strtok(NULL, " \t");
+-      }
+-      free(s);
+-    }
+-    else {
+-      char *path;
+-      char *home = getenv("HOME");
+-      if (!home) home = ".";
+-      path = malloc(strlen(home) + 1 + sizeof(".rblcheckrc"));
+-      sprintf(path, "%s/.rblcheckrc", home);
+-      if (!addzonefile(path))
+-        addzonefile("/etc/rblcheckrc");
+-      free(path);
+-    }
+-  }
+-  if (!nzones) {
+-    fprintf(stderr, "%s: no service (zone) list specified (-s or -S option)\n",
+-            progname);
+-    return 1;
+-  }
+-
+-  argv += optind;
+-  argc -= optind;
+-
+-  if (!argc)
+-    return 0;
+-
+-  if (dns_init(0) < 0) {
+-    fprintf(stderr, "%s: unable to initialize DNS library: %s\n",
+-            progname, strerror(errno));
+-    return 1;
+-  }
+-  if (nameserver) {
+-    dns_add_serv(NULL, NULL);
+-    if (dns_add_serv(NULL, nameserver) < 0)
+-      fprintf(stderr, "%s: unable to use nameserver %s: %s\n",
+-              progname, nameserver, strerror(errno));
+-  }
+-  if (dns_open(NULL) < 0) {
+-    fprintf(stderr, "%s: unable to initialize DNS library: %s\n",
+-            progname, strerror(errno));
+-    return 1;
+-  }
+-
+-  for (c = 0; c < argc; ++c) {
+-    if (c && (verbose > 1 || (verbose == 1 && do_txt))) putchar('\n');
+-    ipc.name = argv[c];
+-    submit(&ipc);
+-    waitdns(&ipc);
+-    display_result(&ipc);
+-    if (stopfirst > 1 && listed) break;
+-  }
+-
+-  return listed ? 100 : failures ? 2 : 0;
+-}
+diff --git a/udns/source/udns.3 b/udns/source/udns.3
+deleted file mode 100644
+index 06d2a14..0000000
+--- a/udns/source/udns.3
++++ /dev/null
+@@ -1,1284 +0,0 @@
+-.\" $Id: udns.3,v 1.26 2006/11/28 22:58:04 mjt Exp $
+-.\" udns library manpage
+-.\"
+-.\" Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-.\" This file is part of UDNS library, an async DNS stub resolver.
+-.\"
+-.\" This library is free software; you can redistribute it and/or
+-.\" modify it under the terms of the GNU Lesser General Public
+-.\" License as published by the Free Software Foundation; either
+-.\" version 2.1 of the License, or (at your option) any later version.
+-.\"
+-.\" This library 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
+-.\" Lesser General Public License for more details.
+-.\"
+-.\" You should have received a copy of the GNU Lesser General Public
+-.\" License along with this library, in file named COPYING.LGPL; if not,
+-.\" write to the Free Software Foundation, Inc., 59 Temple Place,
+-.\" Suite 330, Boston, MA  02111-1307  USA
+-
+-.TH udns 3 "Apr 2005" "Library Functions"
+-
+-.SH NAME
+-udns \- stub DNS resolver library
+-
+-.SH SYNOPSYS
+-.nf
+-#include <udns.h>
+-struct \fBdns_ctx\fR;
+-struct \fBdns_query\fR;
+-extern struct dns_ctx \fBdns_defctx\fR;
+-struct dns_ctx *\fIctx\fR;
+-typedef void \fBdns_query_fn\fR(\fIctx\fR, void *\fIresult\fR, void *\fIdata\fR);
+-typedef int
+-\fBdns_parse_fn\fR(const unsigned char *\fIqnd\fR,
+-       const unsigned char *\fIpkt\fR,
+-       const unsigned char *\fIcur\fR,
+-       const unsigned char *\fIend\fR,
+-       void **\fIresultp\fR);
+-
+-\fBcc\fR ... -l\fBudns\fR
+-.fi
+-
+-.SH DESCRIPTION
+-
+-.PP
+-The DNS library, \fBudns\fR, implements thread-safe stub DNS resolver
+-functionality, which may be used both traditional, syncronous way
+-and asyncronously, with application-supplied event loop.
+-
+-.PP
+-While DNS works with both TCP and UDP, performing UDP query first and
+-if the result does not fit in UDP buffer (512 bytes max for original
+-DNS protocol), retrying the query over TCP, the library uses UDP only,
+-but uses EDNS0 (RFC2671) extensions which allows larger UDP buffers.
+-
+-.PP
+-The library uses single UDP socket to perform all operations even when
+-asking multiple nameservers.  This way, it is very simple to use the
+-library in asyncronous event-loop applications: an application should
+-add only single socket to the set of filedescriptors it monitors for I/O.
+-
+-.PP
+-The library uses two main objects, \fIresolver context\fR of type
+-\fBstruct\ dns_ctx\fR, and \fIquery structure\fR of type
+-\fBstruct\ dns_query\fR, both are opaque for an application.
+-Resolver context holds global information about the resolver,
+-such as list of nameservers to use, list of active requests and the like.
+-Query objects holds information about a single DNS query in progress and
+-are allocated/processed/freed by the library.   Pointer to query structure
+-may be treated as an identifier of an in-progress query and may be used
+-to cancel the asyncronous query or to wait for it to complete.
+-
+-.PP
+-Asyncronous interface works as follows.  An application initializes
+-resolver context, submits any number of queries for it using one of
+-supplied \fBdns_submit_\fIXXX\fR() routines (each return the query
+-identifier as pointer to query structure), waits for input on the
+-UDP socket used by the library, and gives some control to the library
+-by calling \fBdns_ioevent\fR() and \fBdns_timeouts\fR() routines when
+-appropriate.  The library performs all necessary processing and executes
+-application supplied callback routine when a query completes (either
+-successefully or not), giving it the result if any, pointer to the
+-resolver context (from which completion status may be obtained), and
+-the data pointer supplied by an application when the query has been
+-submitted.  When submitting a query, an application requests how to
+-handle the reply -- to either return raw DNS reply packet for its
+-own low-level processing, or it may provide an address of \fIparsing
+-routine\fR of type \fBdns_parse_fn\fR to perform conversion of on-wire
+-format into easy to use data structure (the library provides parsing
+-routines for several commonly used resource record types, as well as
+-type-safe higher-level inteface that requests parsing automatically).
+-The I/O monitoring and timeout handling may be either traditional
+-select() or poll() based, or any callback-driven technique may be
+-used.
+-
+-.PP
+-Additionally, the library provides traditional syncronous interface,
+-which may be intermixed with asyncronous calls (during syncronous
+-query processing, other asyncronous queries for the same resolver
+-context continued to be processed as usual).  An application uses
+-one of numerous \fBdns_resolve_\fIXXX\fR() routines provided by the
+-library to perform a query.  As with asyncronous interface, an
+-application may either request to return raw DNS packet or type-specific
+-data structure by providing the parsing routine to handle the reply.
+-Every routine from \fBdns_resolve_\fIXXX\fR() series return pointer
+-to result or NULL in case of any error.  Query completion status
+-(or length of the raw DNS packet) is available from the resolver
+-context using \fBdns_status\fR() routine, the same way as for the
+-asyncronous interface.
+-
+-.PP
+-Internally, library uses on-wire format of domain names, referred
+-to as \fIDN format\fR in this manual page.  This is a series of domain
+-\fIlabels\fR whith preceeding length byte, terminated by zero-length
+-label wich is integral part of the DN format.  There are several routines
+-provided to convert from traditional asciiz string to DN and back.
+-Higher-level type-specific query interface hides the DN format from
+-an application.
+-
+-.SH "COMMON DEFINITIONS"
+-
+-.PP
+-Every DNS Resource Record (RR) has a \fItype\fR and a \fIclass\fR.
+-The library defines several integer constants, \fBDNS_C_\fIXXX\fR and
+-\fBDNS_T_\fIXXX\fR, to use as symbolic names for RR classes and types,
+-such as \fBDNS_C_IN\fR for Internet class, \fBDNS_T_A\fR for IPv4
+-address record type and so on.  See udns.h header file for complete list
+-of all such constants.
+-
+-.PP
+-The following constants are defined in dns.h header file:
+-.IP "\fBDNS_MAXDN\fR (255 bytes)"
+-Maximum length of the domain name in internal (on-wire) DN format.
+-.IP "\fBDNS_MAXLABEL\fR (63 bytes)"
+-Maximum length of a single label in DN format.
+-.IP "\fBDNS_MAXNAME\fR (1024 bytes)"
+-Maximum length of asciiz format of a domain name.
+-.IP "\fBDNS_HSIZE\fR (12 bytes)"
+-Size of header in DNS packet.
+-.IP "\fBDNS_PORT\fR (53)"
+-Default port to use when contacting a DNS server.
+-.IP "\fBDNS_MAXSERV\fR (6 servers)"
+-Maximum number of DNS servers to use.
+-.IP "\fBDNS_MAXSRCH\fR (5 search list entries)"
+-Maximum number of domain search list
+-.IP "\fBDNS_MAXPACKET\fR (512 bytes)"
+-Maximum length of DNS UDP packet as specified by original DNS protocol
+-.IP "\fBDNS_EDNS0PACKET\fR (4096 bytes)"
+-Default length of DNS UDP packet (with EDNS0 extensions) the library uses.
+-Note that recursive nameservers usually resides near the client asking them
+-to resolve names, e.g. on the same LAN segment or even on the same host, so
+-UDP packet fragmentation isn't a problem in most cases.  Note also that
+-the size of actual packets will be as many bytes as actual reply size requires,
+-which is smaller than this value in almost all cases.
+-
+-.PP
+-Additionally, several constants are defined to simplify work with raw DNS
+-packets, such as DNS response codes (\fBDNS_R_\fIXXX\fR), DNS header layout
+-(\fBDNS_H_\fIXXX\fR) and others.  Again, see udns.h for complete list.
+-Library error codes (\fBDNS_E_\fIXXX\fR) are described later in this
+-manual page.
+-
+-.SH "RESOLVER CONTEXT"
+-
+-.PP
+-Resolver context, of type \fBstruct\ dns_ctx\fR, is an object which is
+-opaque to an application.  Several routines provided by the library
+-to initialize, copy and free resolver contexts.  Most other high-level
+-routines in this library expects a pointer to resolver context, \fIctx\fR,
+-as the first argument.  There is a default resolver context available,
+-named \fBdns_defctx\fR.  When the context pointer \fIctx\fR passed to
+-a routine is NULL, \fBdns_defctx\fR is used.  Several resolver contexts
+-may be active at the same time, for example, when an application is
+-multi-threaded and each thread uses resolver.
+-.PP
+-When initializing resolver context, the library uses information from
+-system file /etc/resolv.conf (see \fBresolv.conf\fR(5)), consults
+-environment variables \fB$LOCALDOMAIN\fR, \fB$DNSCACHEIP\fR,
+-\fB$NAMESERVERS\fR and \fB$RES_OPTIONS\fR, and local host name to obtain
+-list of local nameservers, domain name search list and various resolver
+-options.
+-.PP
+-The following routines to initialize resolver context are available:
+-.PP
+-.nf
+-int \fBdns_init\fR(int \fIdo_open\fR)
+-struct dns_ctx *\fBdns_new\fR(struct dns_ctx *\fIcopy\fR)
+-void \fBdns_free\fR(\fIctx\fR)
+-.fi
+-.RS
+-\fBdns_init\fR() initializes default resolver context, \fBdns_defctx\fR,
+-and optionally opens it (if \fIdo_open\fR is true) using \fBdns_open\fR(),
+-returning negative value on error.
+-\fBdns_new\fR() makes a copy of a given resolver context \fIcopy\fR, or
+-default context if \fIcopy\fR is NULL, and returns pointer to it.
+-\fBdns_new\fR() may fail if there's no memory available to make a copy
+-of \fIcopy\fR, in which case the routine will return NULL pointer.
+-\fBdns_free\fR() is used to close assotiated socket and free resolver
+-context resources and cancelling (abandoming) all active queries
+-assotiated with it.  It's ok to free \fBdns_defctx\fR as well as
+-dynamically allocated contexts returned by \fBdns_new\fR().
+-.RE
+-.PP
+-.nf
+-int \fBdns_add_serv\fR(\fIctx\fR, const char *\fIserv\fR)
+-int \fBdns_add_serv_s\fR(\fIctx\fR, const struct sockaddr *\fIsa\fR)
+-int \fBdns_add_srch\fR(\fIctx\fR, const char *\fIsrch\fR)
+-.fi
+-.RS
+-Add an element to list of nameservers (\fBdns_add_serv\fR(), as
+-asciiz-string \fIserv\fR with an IP address of the nameserver,
+-and \fBdns_add_serv_s\fR(), as initialized socket address \fIsa\fR),
+-or search list (\fBdns_add_srch\fR(), as a pointer to domain name)
+-for the given context \fIctx\fR.  If the last argument is a NULL
+-pointer, the corresponding list (search or nameserver) is reset
+-instead.  Upon successeful completion, each routine returns new
+-number of elements in the list in question.  On error, negative
+-value is returned and global variable \fBerrno\fR is set appropriately.
+-It is an error to call any of this functions if the context is
+-opened (after \fBdns_open\fR() or \fBdns_init\fR() with non-zero argument).
+-.RE
+-.PP
+-.nf
+-int \fBdns_set_opts\fR(\fIctx\fR, const char *\fIopts\fR)
+-.fi
+-.RS
+-set resolver context options from \fIopts\fR string, in the same way as
+-processing \fBoptions\fR statement in resolv.conf and \fB$RES_OPTIONS\fR
+-environment variable.
+-.RE
+-.PP
+-.nf
+-void \fBdns_set_opt\fR(\fIctx\fR, int \fIopt\fR, \fIval\fR)
+-.fi
+-.RS
+-.B TODO
+-The \fIflags\fR argument is a bitmask with the following bits defined:
+-.IP \fBDNS_NOSRCH\fR
+-do not perform domain name search in search list.
+-.IP \fBDNS_NORD\fR
+-do not request recursion when performing queries
+-(i.e. don't set RD flag in querues).
+-.IP \fBDNS_AAONLY\fR
+-request authoritative answers only (i.e. set AA
+-flag in queries).
+-.RE
+-
+-.PP
+-.nf
+-int \fBdns_open\fR(\fIctx\fR)
+-int \fBdns_sock\fR(const \fIctx\fR)
+-void \fBdns_close\fR(\fIctx\fR)
+-.fi
+-.RS
+-\fBdns_open\fR() opens the UDP socket used for queries if not already
+-open, and return assotiated filedescriptor (or negative value in case
+-of error).
+-\fBdns_sock\fR() return the UDP socket if open, or -1 if not.
+-\fBdns_close\fR() closes the UDP socket if it was open.
+-.RE
+-
+-.PP
+-.nf
+-int \fBdns_active\fR(const \fIctx\fR)
+-.fi
+-.RS
+-return number of active queries queued for the given context
+-\fIctx\fR, or zero if none.
+-.RE
+-
+-.PP
+-.nf
+-int \fBdns_status\fR(const \fIctx\fR)
+-.fi
+-.RS
+-return status code from last operation.  When using syncronous
+-interface, this is the query completion status of the last query.
+-With asyncronous interface, from within the callback routine,
+-this is the query completion status of the query for which the
+-callback is being called.  When query submission fails, this
+-is the error code indicating failure reason.  All error codes
+-are negative and are represented by \fBDNS_E_\fIXXX\fR constants
+-described below.
+-.RE
+-
+-.PP
+-.nf
+-void \fBdns_ioevent\fR(\fIctx\fR, time_t \fInow\fR)
+-.fi
+-.RS
+-this routine may be called by an application to process I/O
+-events on the UDP socket used by the library, as returned
+-by \fBdns_sock\fR().  The routine tries to receive incoming
+-UDP datagram from the socket and process it.  The socket is
+-set up to be non-blocking, so it is safe to call the routine
+-even if there's no data to read.  The routine will process
+-as many datagrams as are queued for the socket, so it is
+-safe to use it with either level-triggered or edge-triggered
+-I/O monitoring model.  The \fInow\fR argument is either a
+-current time as returned by \fBtime\fR(), or 0, in which
+-case the routine will obtain current time by it's own.
+-.RE
+-
+-.PP
+-.nf
+-int \fBdns_timeouts\fR(\fIctx\fR, int \fImaxwait\fR, time_t \fInow\fR)
+-.fi
+-.RS
+-process any pending timeouts and return number of secounds
+-from current time (\fInow\fR if it is not 0) to the time when
+-the library wants the application to pass it control to process
+-more queued requests.  In case when there are no requests pending,
+-this time is -1.  The routine will not request a time larger than
+-\fImaxwait\fR secounds if it is greather or equal to zero.  If
+-\fInow\fR is 0, the routine will obtain current time by it's own;
+-when it is not 0, it should contain current time as returned by
+-\fBtime\fR().
+-.RE
+-
+-.PP
+-.nf
+-typedef void \fBdns_utm_fn\fR(\fIctx\fR, int \fItimeout\fR, void *\fIdata\fR)
+-void \fBdns_set_cbck\fR(\fIctx\fR, dns_utm_fn *\fIutmfn\fR, void *\fIdata\fR)
+-.fi
+-.RS
+-An application may use custom callback-based I/O multiplexing mechanism.
+-Usually such a mechanism have concept of a \fItimer\fR, and an ability
+-to register a timer event in a form of a callback routine which will
+-be executed after certain amount of time.  In order to use such an
+-event mechanism, udns provides an ability to register and de-register
+-timer events necessary for internal processing using whatever event
+-mechanism an application uses.  For this to work, it is possible to
+-assotiate a pointer to a routine that will perform necessary work for
+-(de)registering timer events with a given resolver context, and
+-udns will call that routine at appropriate times.  Prototype of
+-such a routine is shown by \fBdns_utm_fn\fR typedef above.  Libudns
+-assotiates single timer with resolver context.  User-supplied \fIutmfn\fR
+-routine will be called by the library with the following arguments:
+-.IP "\fIctx\fR == NULL"
+-delete user timer, at context free time or when an application changes
+-user timer request routine using \fBdns_set_cbck\fR();
+-.IP "\fIctx\fR != NULL, \fItimeout\fR < 0"
+-don't fire timer anymore, when there are no active requests;
+-.IP "\fIctx\fR != NULL, \fItimeout\fR == 0"
+-fire timer at the next possibility, but not immediately;
+-.IP "\fIctx\fR != NULL, \fItimeout\fR > 0"
+-fire timer after \fItimeout\fR seconds after now.
+-.PP
+-The \fIdata\fR argument passed to the routine will be the same
+-as passed to \fBdns_set_cbck\fR().
+-.PP
+-When a timer expires, an application should call \fBdns_tmeouts\fR()
+-routine (see below).  Non-callback timer usage is provided too.
+-.RE
+-
+-.PP
+-.B XXXX TODO: some more resolver context routines, like dns_set_dbgfn() etc.
+-
+-.SH "QUERY INTERFACE"
+-
+-.PP
+-There are two ways to perform DNS queries: traditional syncronous
+-way, when udns performs all the necessary processing and return
+-control to the application only when the query completes, and
+-asyncronous way, when an application submits one or more queries
+-to the library using given resolver context, and waits for completion
+-by monitoring filedescriptor used by library and calling library
+-routines to process input on that filedescriptor.  Asyncronous mode
+-works with callback routines: an application supplies an address of
+-a routine to execute when the query completes, and a data pointer,
+-which is passed to the callback routine.
+-
+-.PP
+-Queries are submitted to the library in a form of \fBstruct\ dns_query\fR.
+-To perform asyncronous query, an application allocates memory for the
+-\fIquery structure\fR and passes it to the library using \fBdns_submit\fR()
+-routines, together with all the query parameters.  When the query completes,
+-library will call application-supplied callback routine, giving it the
+-resolver context (wich holds query completion status), dynamically allocated
+-result (which will be either raw DNS packet or, if applicatin requested parsing
+-the result by specifying non-NULL parse routine, ready-to-use type-specific
+-structure), and a data pointer provided by an application when it submitted the
+-query.  It is the application who's responsible for freeing the result memory.
+-.PP
+-Generic query callback routine looks like this:
+-.nf
+-typedef void
+-\fBdns_query_fn\fR(\fIctx\fR, void *\fIresult\fR, void *\fIdata\fR)
+-.fi
+-Type-specific query interface expects similar form of callback
+-routine with the only difference in type of \fBresult\fR argument,
+-which will be pointer to specific data structure (decoded reply)
+-instead of this void pointer to raw DNS packet data.
+-
+-.PP
+-Result parsing routine looks like this:
+-.nf
+-typedef int
+-\fBdns_parse_fn\fR(const unsigned char *\fIqdn\fR,
+-      const unsigned char *\fIpkt\fR,
+-      const unsigned char *\fIcur\fR,
+-      const unsigned char *\fIend\fR,
+-      void **\fIresultp\fR);
+-.fi
+-When called by the library, the arguments are as follows:
+-\fIpkt\fR points to the start of the packet received;
+-\fIend\fR points past the end of the packet received;
+-\fIcur\fR points past the query DN in the query section of the
+-packet;
+-\fIqdn\fR points to the original query DN.
+-The routine should allocate a single buffer to hold the result,
+-parse the reply filling in the buffer, and return the buffer
+-using \fIresultp\fR argument.  It returns 0 in case of error,
+-or udns error code (\fBDNS_E_\fIXXX\fR constants) in case of
+-error.
+-Note that by the time when the parse routine is called by the
+-library, packet is already verified to be a reply to the
+-original query, by matching query DN, query class and query type.
+-
+-.PP
+-Type-specific query inteface supplies necessary parsing routines
+-automatically.
+-
+-.PP
+-In case of error, query completion status as returned by
+-\fBdns_status\fR(\fIctx\fR), will contain one of the following values:
+-.IP "positive value"
+-length of raw DNS packet if parsing is not requested.
+-.IP 0
+-the query was successeful and the \fIreply\fR points to type-specific
+-data structure.
+-.IP \fBDNS_E_TEMPFAIL\fR
+-temporary error, the resolver nameserver was not able to
+-process our query or timed out.
+-.IP \fBDNS_E_PROTOCOL\fR
+-protocol error, a nameserver returned malformed reply.
+-.IP \fBDNS_E_NXDOMAIN\fR
+-the domain name does not exist.
+-.IP \fBDNS_E_NODATA\fR
+-there is no data of requested type found.
+-.IP \fBDNS_E_NOMEM\fR
+-out of memory while processing request.
+-.IP \fBDNS_E_BADQUERY\fR
+-some aspect of the query (most common is the domain name in question)
+-is invalid, and the library can't even start a query.
+-
+-.PP
+-Library provides two series of routines which uses similar interface --
+-one for asyncronous queries and another for syncronous queries.  There
+-are two general low-level routines in each series to submit (asyncronous
+-interface) and resolve (syncronous interface) queries, as well as several
+-type-specific routines with more easy-to-use interfaces.  To submit
+-an asyncronous query, use one of \fBdns_submit_\fIXXX\fR() routine, each
+-of which accepts query parameters, pointers to callback routine and to
+-callback data, and optional current time hint.  Note type-specific
+-\fBdns_submit_\fIXXX\fR() routines expects specific type of the callback
+-routine as well, which accepts reply as a pointer to corresponding
+-structure, not a void pointer).  Every \fBdns_submit_\fIXXX\fR() routine
+-return pointer to internal query structure of type struct\ dns_query,
+-used as an identifier for the given query.
+-
+-.PP
+-To resolve a query syncronously, use one of \fBdns_resolve_\fIXXX\fR()
+-routines, which accepts the same query parameters (but not the
+-callback pointers) as corresponding \fBdns_submit_\fIXXX\fR(), and
+-return the query result, which is the same as passed to the callback
+-routine in case of asyncronous interface.
+-
+-.PP
+-In either case, the result memory (if the query completed successefully)
+-is dynamically allocated and should be freed by an application.  If
+-the query failed for any reason, the result will be NULL, and error
+-status will be available from \fBdns_status\fR(\fIctx\fR) routine
+-as shown above.
+-
+-.PP
+-.nf
+-struct dns_query *
+-\fBdns_submit_dn\fR(\fIctx\fR,
+-     const unsigned char *\fIdn\fR, \fIqcls\fR, \fIqtyp\fR, \fIflags\fR,
+-     \fIparse\fR, \fIcbck\fR, \fIdata\fR)
+-struct dns_query *
+-\fBdns_submit_p\fR(\fIctx\fR,
+-     const char *\fIname\fR, \fIqcls\fR, \fIqtyp\fR, \fIflags\fR,
+-     \fIparse\fR, \fIcbck\fR, \fIdata\fR)
+-   enum dns_class \fIqcls\fR;
+-   enum dns_type \fIqtyp\fR;
+-   int \fIflags\fR;
+-   dns_parse_fn *\fIparse\fR;
+-   dns_query_fn *\fIcbck\fR;
+-   void *\fIdata\fR;
+-.fi
+-.RS
+-submit a query for processing for the given resolver context \fIctx\fR.
+-Two routines differs only in 3rd argument, which is domain name in
+-DN format (\fIdn\fR) or asciiz string (\fIname\fR).  The query will be
+-performed for the given domain name, with type \fIqtyp\fR in class \fIqcls\fR,
+-using option bits in \fIflags\fR, using RR parsing routine pointed by
+-\fIparse\fR if not-NULL, and upon completion, \fIcbck\fR function will
+-be called with the \fIdata\fR argument.
+-In case of successeful query submission,
+-the routine return pointer to internal query structure which may be treated
+-as an identifier of the query as used by the library, and may be used as an
+-argument for \fBdns_cancel\fR() routine.  In case of error, NULL will be
+-returned, and context error status (available using \fIdns_status\fR() routine)
+-will be set to corresponding error code, which in this case may be
+-DNS_E_BADQUERY if the \fIname\fR of \fIdn\fR is invalid, DNS_E_NOMEM if
+-there's no memory available to allocate query structure, or DNS_E_TEMPFAIL
+-if an internal error occured.
+-.RE
+-
+-.PP
+-.nf
+-void *\fBdns_resolve_dn\fR(\fIctx\fR,
+-     const unsigned char *\fIdn\fR, \fIqcls\fR, \fIqtyp\fR, \fIflags\fR, \fIparse\fR);
+-void *\fBdns_resolve_p\fR(\fIctx\fR,
+-     const char *\fIname\fR, \fIqcls\fR, \fIqtyp\fR, \fIflags\fR, \fIparse\fR)
+-   enum dns_class \fIqcls\fR;
+-   enum dns_type \fIqtyp\fR;
+-   int \fIflags\fR;
+-   dns_parse_fn *\fIparse\fR;  
+-.fi
+-.RS
+-syncronous interface.  The routines perform all the steps necessary to resolve
+-the given query and return the result.  If there's no positive result for any
+-reason, all the routines return NULL, and set context error status (available 
+-using \fBdns_status\fR() routine) to indicate the error code.  If the query
+-was successeful, context status code will contain either the length of the
+-raw DNS reply packet if \fIparse\fR argument was NULL (in which case the return
+-value is pointer to the reply DNS packet), or 0 (in which case the return value
+-is the result of \fIparse\fR routine).  If the query successeful (return value
+-is not NULL), the memory returned was dynamically allocated by the library
+-and should be free()d by application after use.
+-.RE
+-
+-.PP
+-.nf
+-void *\fBdns_resolve\fR(\fIctx\fR, struct dns_query *\fIq\fR)
+-.fi
+-.RS
+-wait for the given query \fIq\fR, as returned by one of
+-\fBdns_submit_\fIXXX\fR() routines, for completion, and
+-return the result.  The callback routine will not be called
+-for this query.  After completion, the query identifier \fIq\fI
+-is not valid. Both \fBdns_resolve_dn\fR() and \fBdns_resolve_p\fR()
+-are just wrappers around corresponding submit routines and this
+-\fBdns_resolve\fR() routine.
+-.RE
+-
+-.PP
+-.nf
+-void \fBdns_cancel\fR(\fIctx\fR, struct dns_query *\fIq\fR)
+-.fi
+-.RS
+-cancel an active query \fIq\fR, without calling a callback routine.
+-After completion, the query identifier \fIq\fR is not valid.
+-.RE
+-
+-.SH "TYPE-SPECIFIC QUERIES"
+-
+-.PP
+-In addition to the generic low-level query interface, the library provides
+-a set of routines to perform specific queries in a type-safe manner, as
+-well as parsers for several well-known resource record types.  The library
+-implements high-level interface for A, AAAA, PTR, MX and TXT records
+-and DNSBL and RHSBL functionality.  These routines returns specific types
+-as result of a query, instead of raw DNS packets.  The following types
+-and routines are available.
+-
+-.PP
+-.nf
+-struct \fBdns_rr_null\fR {
+-  char *\fBdnsn_qname\fR;     /* original query name */
+-  char *\fBdnsn_cname\fR;     /* canonical name */
+-  unsigned \fBdnsn_ttl\fR;    /* Time-To-Live (TTL) value */
+-  int \fBdnsn_nrr\fR;         /* number of records in the set */
+-};
+-.fi
+-.PP
+-NULL RR set, used as a base for all other RR type structures.
+-Every RR structure as used by the library have four standard
+-fields as in struct\ \fBdns_rr_null\fR.
+-
+-.SS "IN A Queries"
+-.PP
+-.nf
+-struct \fBdns_rr_a4\fR {       /* IN A RRset */
+-  char *\fBdnsa4_qname\fR;     /* original query name */
+-  char *\fBdnsa4_cname\fR;     /* canonical name */
+-  unsigned \fBdnsa4_ttl\fR;    /* Time-To-Live (TTL) value */
+-  int \fBdnsa4_nrr\fR;         /* number of addresses in the set */
+-  struct in_addr \fBdnsa4_addr\fR[]; /* array of addresses */
+-};
+-typedef void
+-  \fBdns_query_a4_fn\fR(\fIctx\fR, struct dns_rr_a4 *\fIresult\fR, \fIdata\fR)
+-dns_parse_fn \fBdns_parse_a4\fB;
+-struct dns_query *
+-\fBdns_submit_a4\fB(\fIctx\fR, const char *\fIname\fR, int \fIflags\fR,
+-   dns_query_a4_fn *\fIcbck\fR, \fIdata\fR);
+-struct dns_rr_a4 *
+-\fBdns_resolve_a4\fB(\fIctx\fR, const char *\fIname\fR, int \fIflags\fR);
+-.fi
+-.PP
+-The \fBdns_rr_a4\fR structure holds a result of an \fBIN A\fR query,
+-which is an array of IPv4 addresses.  Callback routine for IN A queries
+-expected to be of type \fBdns_query_a4_fn\fR, which expects pointer to
+-\fBdns_rr_a4\fR structure as query result instead of raw DNS packet.
+-The \fBdns_parse_a4\fR() is used to convert raw DNS reply packet into
+-\fBdns_rr_a4\fR structure (it is used internally and may be used directly too
+-with generic query interface).  Routines \fBdns_submit_a4\fR() and
+-\fBdns_resolve_a4\fR() are used to perform A IN queries in a type-safe
+-manner.  The \fIname\fR parameter is the domain name in question, and
+-\fIflags\fR is query flags bitmask, with one bit, DNS_NOSRCH, of practical
+-interest (if the \fIname\fR is absolute, that is, it ends up with a dot,
+-DNS_NOSRCH flag will be set automatically).
+-
+-.SS "IN AAAA Queries"
+-.PP
+-.nf
+-struct \fBdns_rr_a6\fR {       /* IN AAAA RRset */
+-  char *\fBdnsa6_qname\fR;     /* original query name */
+-  char *\fBdnsa6_cname\fR;     /* canonical name */
+-  unsigned \fBdnsa6_ttl\fR;    /* Time-To-Live (TTL) value */
+-  int \fBdnsa6_nrr\fR;         /* number of addresses in the set */
+-  struct in6_addr \fBdnsa6_addr\fR[]; /* array of addresses */
+-};
+-typedef void
+-  \fBdns_query_a6_fn\fR(\fIctx\fR, struct dns_rr_a6 *\fIresult\fR, \fIdata\fR)
+-dns_parse_fn \fBdns_parse_a6\fB;
+-struct dns_query *
+-\fBdns_submit_a6\fB(\fIctx\fR, const char *\fIname\fR, int \fIflags\fR,
+-   dns_query_a6_fn *\fIcbck\fR, \fIdata\fR);
+-struct dns_rr_a6 *
+-\fBdns_resolve_a6\fB(\fIctx\fR, const char *\fIname\fR, int \fIflags\fR);
+-.fi
+-.PP
+-The \fBdns_rr_a6\fR structure holds a result of an \fBIN AAAA\fR query,
+-which is an array of IPv6 addresses.  Callback routine for IN AAAA queries
+-expected to be of type \fBdns_query_a6_fn\fR, which expects pointer to
+-\fBdns_rr_a6\fR structure as query result instead of raw DNS packet.
+-The \fBdns_parse_a6\fR() is used to convert raw DNS reply packet into
+-\fBdns_rr_a6\fR structure (it is used internally and may be used directly too
+-with generic query interface).  Routines \fBdns_submit_a6\fR() and
+-\fBdns_resolve_a6\fR() are used to perform AAAA IN queries in a type-safe
+-manner.  The \fIname\fR parameter is the domain name in question, and
+-\fIflags\fR is query flags bitmask, with one bit, DNS_NOSRCH, of practical
+-interest (if the \fIname\fR is absolute, that is, it ends up with a dot,
+-DNS_NOSRCH flag will be set automatically).
+-
+-.SS "IN PTR Queries"
+-.PP
+-.nf
+-struct \fBdns_rr_ptr\fR {       /* IN PTR RRset */
+-  char *\fBdnsptr_qname\fR;     /* original query name */
+-  char *\fBdnsptr_cname\fR;     /* canonical name */
+-  unsigned \fBdnsptr_ttl\fR;    /* Time-To-Live (TTL) value */
+-  int \fBdnsptr_nrr\fR;         /* number of domain name pointers */
+-  char *\fBdnsptr_ptr\fR[];     /* array of domain name pointers */
+-};
+-typedef void
+-  \fBdns_query_ptr_fn\fR(\fIctx\fR, struct dns_rr_ptr *\fIresult\fR, \fIdata\fR)
+-dns_parse_fn \fBdns_parse_ptr\fB;
+-struct dns_query *
+-\fBdns_submit_a4ptr\fB(\fIctx\fR, const struct in_addr *\fBaddr\fR,
+-   dns_query_ptr_fn *\fIcbck\fR, \fIdata\fR);
+-struct dns_rr_ptr *
+-\fBdns_resolve_a4ptr\fB(\fIctx\fR, const struct in_addr *\fBaddr\fR);
+-struct dns_query *
+-\fBdns_submit_a6ptr\fB(\fIctx\fR, const struct in6_addr *\fBaddr\fR,
+-   dns_query_ptr_fn *\fIcbck\fR, \fIdata\fR);
+-struct dns_rr_ptr *
+-\fBdns_resolve_a6ptr\fB(\fIctx\fR, const struct in6_addr *\fBaddr\fR);
+-.fi
+-.PP
+-The \fBdns_rr_ptr\fR structure holds a result of an IN PTR query, which
+-is an array of domain name pointers for a given IPv4 or IPv6 address.
+-Callback routine for IN PTR queries expected to be of type
+-\fBdns_query_ptr_fn\fR, which expects pointer to \fBdns_rr_ptr\fR
+-structure as query result instead of raw DNS packet.  The \fBdns_parse_ptr\fR()
+-is used to convert raw DNS reply packet into \fBdns_rr_ptr\fR structure
+-(it is used internally and may be used directly too with generic query
+-interface).  Routines \fBdns_submit_a4ptr\fR() and \fBdns_resolve_a4ptr\fR()
+-are used to perform IN PTR queries for IPv4 addresses in a type-safe
+-manner. Routines \fBdns_submit_a6ptr\fR() and \fBdns_resolve_a6ptr\fR()
+-are used to perform IN PTR queries for IPv6 addresses.
+-
+-.SS "IN MX Queries"
+-.PP
+-.nf
+-struct \fBdns_mx\fR {          /* single MX record */
+-  int \fBpriority\fR;          /* priority value of this MX */
+-  char *\fBname\fR;            /* domain name of this MX */
+-};
+-struct \fBdns_rr_mx\fR {       /* IN MX RRset */
+-  char *\fBdnsmx_qname\fR;     /* original query name */
+-  char *\fBdnsmx_cname\fR;     /* canonical name */
+-  unsigned \fBdnsmx_ttl\fR;    /* Time-To-Live (TTL) value */
+-  int \fBdnsmx_nrr\fR;         /* number of mail exchangers in the set */
+-  struct dns_mx \fBdnsmx_mx\fR[]; /* array of mail exchangers */
+-};
+-typedef void
+-  \fBdns_query_mx_fn\fR(\fIctx\fR, struct dns_rr_mx *\fIresult\fR, \fIdata\fR)
+-dns_parse_fn \fBdns_parse_mx\fB;
+-struct dns_query *
+-\fBdns_submit_mx\fB(\fIctx\fR, const char *\fIname\fR, int \fIflags\fR,
+-   dns_query_mx_fn *\fIcbck\fR, \fIdata\fR);
+-struct dns_rr_mx *
+-\fBdns_resolve_mx\fB(\fIctx\fR, const char *\fIname\fR, int \fIflags\fR);
+-.fi
+-.PP
+-The \fBdns_rr_mx\fR structure holds a result of an IN MX query, which
+-is an array of mail exchangers for a given domain.  Callback routine for IN MX
+-queries expected to be of type \fBdns_query_mx_fn\fR, which expects pointer to
+-\fBdns_rr_mx\fR structure as query result instead of raw DNS packet.
+-The \fBdns_parse_mx\fR() is used to convert raw DNS reply packet into
+-\fBdns_rr_mx\fR structure (it is used internally and may be used directly too
+-with generic query interface).  Routines \fBdns_submit_mx\fR() and
+-\fBdns_resolve_mx\fR() are used to perform IN MX queries in a type-safe
+-manner.  The \fIname\fR parameter is the domain name in question, and
+-\fIflags\fR is query flags bitmask, with one bit, DNS_NOSRCH, of practical
+-interest (if the \fIname\fR is absolute, that is, it ends up with a dot,
+-DNS_NOSRCH flag will be set automatically).
+-
+-.SS "TXT Queries"
+-.PP
+-.nf
+-struct \fBdns_txt\fR {          /* single TXT record */
+-  int \fBlen\fR;                /* length of the text */
+-  unsigned char *\fBtxt\fR;     /* pointer to the text */
+-};
+-struct \fBdns_rr_txt\fR {       /* TXT RRset */
+-  char *\fBdnstxt_qname\fR;     /* original query name */
+-  char *\fBdnstxt_cname\fR;     /* canonical name */
+-  unsigned \fBdnstxt_ttl\fR;    /* Time-To-Live (TTL) value */
+-  int \fBdnstxt_nrr\fR;         /* number of text records in the set */
+-  struct dns_txt \fBdnstxt_txt\fR[]; /* array of TXT records */
+-};
+-typedef void
+-  \fBdns_query_txt_fn\fR(\fIctx\fR, struct dns_rr_txt *\fIresult\fR, \fIdata\fR)
+-dns_parse_fn \fBdns_parse_txt\fB;
+-struct dns_query *
+-\fBdns_submit_txt\fB(\fIctx\fR, const char *\fIname\fR, enum dns_class \fIqcls\fR,
+-   int \fIflags\fR, dns_query_txt_fn *\fIcbck\fR, \fIdata\fR);
+-struct dns_rr_txt *
+-\fBdns_resolve_txt\fB(\fIctx\fR, const char *\fIname\fR,
+-             enum dns_class \fIqcls\fR, int \fIflags\fR);
+-.fi
+-.PP
+-The \fBdns_rr_txt\fR structure holds a result of a TXT query, which is an
+-array of text records for a given domain name.  Callback routine for TXT
+-queries expected to be of type \fBdns_query_txt_fn\fR, which expects pointer
+-to \fBdns_rr_txt\fR structure as query result instead of raw DNS packet.
+-The \fBdns_parse_txt\fR() is used to convert raw DNS reply packet into
+-\fBdns_rr_txt\fR structure (it is used internally and may be used directly too
+-with generic query interface).  Routines \fBdns_submit_txt\fR() and
+-\fBdns_resolve_txt\fR() are used to perform IN MX queries in a type-safe
+-manner.  The \fIname\fR parameter is the domain name in question, and
+-\fIflags\fR is query flags bitmask, with one bit, DNS_NOSRCH, of practical
+-interest (if the \fIname\fR is absolute, that is, it ends up with a dot,
+-DNS_NOSRCH flag will be set automatically).  Note that each TXT string
+-is represented by \fBstruct\ dns_txt\fR, while zero-terminated (and the
+-len field of the structure does not include the terminator), may contain
+-embedded null characters -- content of TXT records is not interpreted
+-by the library in any way.
+-
+-.SS "SRV Queries"
+-.PP
+-.nf
+-struct \fBdns_srv\fR {          /* single SRV record */
+-  int \fBpriority\fR;           /* priority of the record */
+-  int \fBweight\fR;             /* weight of the record */
+-  int \fBport\fR;               /* the port number to connect to */
+-  char *\fBname\fR;             /* target host name */
+-};
+-struct \fBdns_rr_srv\fR {       /* SRV RRset */
+-  char *\fBdnssrv_qname\fR;     /* original query name */
+-  char *\fBdnssrv_cname\fR;     /* canonical name */
+-  unsigned \fBdnssrv_ttl\fR;    /* Time-To-Live (TTL) value */
+-  int \fBdnssrv_nrr\fR;         /* number of text records in the set */
+-  struct dns_srv \fBdnssrv_srv\fR[]; /* array of SRV records */
+-};
+-typedef void
+-  \fBdns_query_srv_fn\fR(\fIctx\fR, struct dns_rr_srv *\fIresult\fR, \fIdata\fR)
+-dns_parse_fn \fBdns_parse_srv\fB;
+-struct dns_query *
+-\fBdns_submit_srv\fB(\fIctx\fR, const char *\fIname\fR, const char *\fIservice\fR, const char *\fIprotocol\fR,
+-   int \fIflags\fR, dns_query_txt_fn *\fIcbck\fR, \fIdata\fR);
+-struct dns_rr_srv *
+-\fBdns_resolve_srv\fB(\fIctx\fR, const char *\fIname\fR, const char *\fIservice\fR, const char *\fIprotocol\fR,
+-             int \fIflags\fR);
+-.fi
+-.PP
+-The \fBdns_rr_srv\fR structure holds a result of an IN SRV (rfc2782) query,
+-which is an array of servers (together with port numbers) which are performing
+-operations for a given \fIservice\fR using given \fIprotocol\fR on a target
+-domain \fIname\fR.  Callback routine for IN SRV queries expected to be of type
+-\fBdns_query_srv_fn\fR, which expects pointer to \fBdns_rr_srv\fR structure as
+-query result instead of raw DNS packet.  The \fBdns_parse_srv\fR() is used to
+-convert raw DNS reply packet into \fBdns_rr_srv\fR structure (it is used
+-internally and may be used directly too with generic query interface).
+-Routines \fBdns_submit_srv\fR() and \fBdns_resolve_srv\fR() are used to
+-perform IN SRV queries in a type-safe manner.  The \fIname\fR parameter
+-is the domain name in question, \fIservice\fR and \fRprotocl\fR specifies the
+-service and the protocol in question (the library will construct query DN
+-according to rfc2782 rules) and may be NULL (in this case the library
+-assumes \fIname\fR parameter holds the complete SRV query), and
+-\fIflags\fR is query flags bitmask, with one bit, DNS_NOSRCH, of practical
+-interest (if the \fIname\fR is absolute, that is, it ends up with a dot,
+-DNS_NOSRCH flag will be set automatically).
+-
+-.SS "NAPTR Queries"
+-.PP
+-.nf
+-struct \fBdns_naptr\fR {        /* single NAPTR record */
+-  int \fBorder\fR;              /* record order */
+-  int \fBpreference\fR;         /* preference of this record */
+-  char *\fBflags\fR;            /* application-specific flags */
+-  char *\fBservices\fR;         /* service parameters */
+-  char *\fBregexp\fR;           /* substitutional regular expression */
+-  char *\fBreplacement\fR;      /* replacement string */
+-};
+-struct \fBdns_rr_naptr\fR {     /* NAPTR RRset */
+-  char *\fBdnsnaptr_qname\fR;   /* original query name */
+-  char *\fBdnsnaptr_cname\fR;   /* canonical name */
+-  unsigned \fBdnsnaptr_ttl\fR;  /* Time-To-Live (TTL) value */
+-  int \fBdnsnaptr_nrr\fR;       /* number of text records in the set */
+-  struct dns_naptr \fBdnsnaptr_naptr\fR[]; /* array of NAPTR records */
+-};
+-typedef void
+-  \fBdns_query_naptr_fn\fR(\fIctx\fR, struct dns_rr_naptr *\fIresult\fR, \fIdata\fR)
+-dns_parse_fn \fBdns_parse_naptr\fB;
+-struct dns_query *
+-\fBdns_submit_naptr\fB(\fIctx\fR, const char *\fIname\fR, int \fIflags\fR,
+-   dns_query_txt_fn *\fIcbck\fR, \fIdata\fR);
+-struct dns_rr_naptr *
+-\fBdns_resolve_naptr\fB(\fIctx\fR, const char *\fIname\fR, int \fIflags\fR);
+-.fi
+-.PP
+-The \fBdns_rr_naptr\fR structure holds a result of an IN NAPTR (rfc3403) query.
+-Callback routine for IN NAPTR queries expected to be of type
+-\fBdns_query_naptr_fn\fR, expects pointer to \fBdns_rr_naptr\fR
+-structure as query result instead of raw DNS packet.
+-The \fBdns_parse_naptr\fR() is used to convert raw DNS reply packet into
+-\fBdns_rr_naptr\fR structure (it is used
+-internally and may be used directly too with generic query interface).
+-Routines \fBdns_submit_naptr\fR() and \fBdns_resolve_naptr\fR() are used to
+-perform IN NAPTR queries in a type-safe manner.  The \fIname\fR parameter
+-is the domain name in question, and \fIflags\fR is query flags bitmask,
+-with one bit, DNS_NOSRCH, of practical interest (if the \fIname\fR is
+-absolute, that is, it ends up with a dot, DNS_NOSRCH flag will be set
+-automatically).
+-
+-.SS "DNSBL Interface"
+-.PP
+-A DNS-based blocklists, or a DNSBLs, are in wide use nowadays, especially
+-to protect mailservers from spammers.  The library provides DNSBL interface,
+-a set of routines to perform queries against DNSBLs.  Routines accepts an
+-IP address (IPv4 and IPv6 are both supported) and a base DNSBL zone as
+-query parameters, and returns either \fBdns_rr_a4\fR or \fBdns_rr_txt\fR
+-structure.  Note that IPv6 interface return IPv4 RRset.
+-.PP
+-.nf
+-struct dns_query *
+-\fBdns_submit_a4dnsbl\fR(\fIctx\fR,
+-  const struct in_addr *\fIaddr\fR, const char *\fIdnsbl\fR,
+-  dns_query_a4_fn *\fIcbck\fR, void *\fIdata\fR);
+-struct dns_query *
+-\fBdns_submit_a4dnsbl_txt\fR(\fIctx\fR,
+-  const struct in_addr *\fIaddr\fR, const char *\fIdnsbl\fR,
+-  dns_query_txt_fn *\fIcbck\fR, void *\fIdata\fR);
+-struct dns_query *
+-\fBdns_submit_a6dnsbl\fR(\fIctx\fR,
+-  const struct in6_addr *\fIaddr\fR, const char *\fIdnsbl\fR,
+-  dns_query_a4_fn *\fIcbck\fR, void *\fIdata\fR);
+-struct dns_query *
+-\fBdns_submit_a6dnsbl_txt\fR(\fIctx\fR,
+-  const struct in6_addr *\fIaddr\fR, const char *\fIdnsbl\fR,
+-  dns_query_txt_fn *\fIcbck\fR, void *\fIdata\fR);
+-struct dns_rr_a4 *\fBdns_resolve_a4dnsbl\fR(\fIctx\fR,
+-  const struct in_addr *\fIaddr\fR, const char *\fIdnsbl\fR)
+-struct dns_rr_txt *\fBdns_resolve_a4dnsbl_txt\fR(\fIctx\fR,
+-  const struct in_addr *\fIaddr\fR, const char *\fIdnsbl\fR)
+-struct dns_rr_a4 *\fBdns_resolve_a6dnsbl\fR(\fIctx\fR,
+-  const struct in6_addr *\fIaddr\fR, const char *\fIdnsbl\fR)
+-struct dns_rr_txt *\fBdns_resolve_a6dnsbl_txt\fR(\fIctx\fR,
+-  const struct in6_addr *\fIaddr\fR, const char *\fIdnsbl\fR)
+-.fi
+-Perform (submit or resolve) a DNSBL query for the given \fIdnsbl\fR
+-domain and an IP \fIaddr\fR in question, requesting either A or TXT
+-records.
+-
+-.SS "RHSBL Interface"
+-.PP
+-RHSBL is similar to DNSBL, but instead of an IP address, the
+-parameter is a domain name.
+-.PP
+-.nf
+-struct dns_query *
+-\fBdns_submit_rhsbl\fR(\fIctx\fR, const char *\fIname\fR, const char *\fIrhsbl\fR,
+-  dns_query_a4_fn *\fIcbck\fR, void *\fIdata\fR);
+-struct dns_query *
+-\fBdns_submit_rhsbl_txt\fR(\fIctx\fR, const char *\fIname\fR, const char *\fIrhsbl\fR,
+-  dns_query_txt_fn *\fIcbck\fR, void *\fIdata\fR);
+-struct dns_rr_a4 *
+-\fBdns_resolve_rhsbl\fR(\fIctx\fR, const char *\fIname\fR, const char *\fIrhsbl\fR);
+-struct dns_rr_txt *
+-\fBdns_resolve_rhsbl_txt\fR(\fIctx\fR, const char *\fIname\fR, const char *\fIrhsbl\fR);
+-.fi
+-Perform (submit or resolve) a RHSBL query for the given \fIrhsbl\fR
+-domain and \fIname\fR in question, requesting either A or TXT records.
+-
+-
+-.SH "LOW-LEVEL INTERFACE"
+-
+-.SS "Domain Names (DNs)"
+-
+-.PP
+-A DN is a series of domain name labels each starts with length byte,
+-followed by empty label (label with zero length).  The following
+-routines to work with DNs are provided.
+-
+-.PP
+-.nf
+-unsigned \fBdns_dnlen\fR(const unsigned char *\fIdn\fR)
+-.fi
+-.RS
+-return length of the domain name \fIdn\fR, including the terminating label.
+-.RE
+-
+-.PP
+-.nf
+-unsigned \fBdns_dnlabels\fR(const unsigned char *\fIdn\fR)
+-.fi
+-.RS
+-return number of non-zero labels in domain name \fIdn\fR.
+-.RE
+-
+-.PP
+-.nf
+-unsigned \fBdns_dnequal\fR(\fIdn1\fR, \fIdn2\fR)
+-  const unsigned char *\fIdn1\fR, *\fIdn2\fR;
+-.fi
+-.RS
+-test whenever the two domain names, \fIdn1\fR and \fIdn2\fR, are
+-equal (case-insensitive).  Return domain name length if equal
+-or 0 if not.
+-.RE
+-
+-.PP
+-.nf
+-unsigned \fBdns_dntodn\fR(\fIsdn\fR, \fIddn\fR, \fIdnsiz\fR)
+-  const unsigned char *\fIsdn\fR;
+-  unsigned char *\fIddn\fR;
+-  unsigned \fIdnsiz\fR;
+-.fi
+-.RS
+-copies the source domain name \fIsdn\fR to destination buffer \fIddn\fR
+-of size \fIdnsiz\fR.  Return domain name length or 0 if \fIddn\fR is
+-too small.
+-.RE
+-
+-.PP
+-.nf
+-int \fBdns_ptodn\fR(\fIname\fR, \fInamelen\fR, \fIdn\fR, \fIdnsiz\fR, \fIisabs\fR)
+-int \fBdns_sptodn\fR(\fIname\fR, \fIdn\fR, \fIdnsiz\fR)
+-  const char *\fIname\fR; unsigned \fInamelen\fR;
+-  unsigned char *\fIdn\fR; unsigned \fIdnsiz\fR;
+-  int *\fIisabs\fR;
+-.fi
+-.RS
+-convert asciiz name \fIname\fR of length \fInamelen\fR to DN format,
+-placing result into buffer \fIdn\fR of size \fIdnsiz\fR.  Return
+-length of the DN if successeful, 0 if the \fIdn\fR buffer supplied is
+-too small, or negative value if \fIname\fR is invalid.  If \fIisabs\fR
+-is non-NULL and conversion was successeful, *\fIisabs\fR will be set to
+-either 1 or 0 depending whenever \fIname\fR was absolute (i.e. ending with
+-a dot) or not.  Name length, \fInamelength\fR, may be zero, in which case
+-strlen(\fIname\fR) will be used.  Second form, \fBdns_sptodn\fR(), is a
+-simplified form of \fBdns_ptodn\fR(), equivalent to
+-.br
+-.nf
+-\fBdns_ptodn\fR(\fIname\fR, 0, \fIdn\fR, \fIdnlen\fR, 0).
+-.fi
+-.RE
+-
+-.PP
+-.nf
+-extern const unsigned char \fBdns_inaddr_arpa_dn\fR[]
+-int \fBdns_a4todn\fR(const struct in_addr *\fIaddr\fR, const unsigned char *\fItdn\fR,
+-      unsigned char *\fIdn\fR, unsigned \fIdnsiz\fR)
+-int \fBdns_a4ptodn\fR(const struct in_addr *\fIaddr\fR, const char *\fItname\fR,
+-      unsigned char *\fIdn\fR, unsigned \fIdnsiz\fR)
+-extern const unsigned char \fBdns_ip6_arpa_dn\fR[]
+-int \fBdns_a6todn\fR(const struct in6_addr *\fIaddr\fR, const unsigned char *\fItdn\fR,
+-      unsigned char *\fIdn\fR, unsigned \fIdnsiz\fR)
+-int \fBdns_a6ptodn\fR(const struct in6_addr *\fIaddr\fR, const char *\fItname\fR,
+-      unsigned char *\fIdn\fR, unsigned \fIdnsiz\fR)
+-.fi
+-.RS
+-several variants of routines to convert IPv4 and IPv6 address \fIaddr\fR
+-into reverseDNS-like domain name in DN format, storing result in \fIdn\fR
+-of size \fIdnsiz\fR.  \fItdn\fR (or \fItname\fR) is the base zone name,
+-like in-addr.arpa for IPv4 or in6.arpa for IPv6.  If \fItdn\fR (or \fItname\fR)
+-is NULL, \fBdns_inaddr_arpa_dn\fR (or \fBdns_ip6_arpa_dn\fR) will be used.
+-The routines may be used to construct a DN for a DNSBL lookup for example.
+-All routines return length of the resulting DN on success, -1 if resulting
+-DN is invalid, or 0 if the \fIdn\fR buffer (\fIdnsiz\fR) is too small.
+-To hold standard rDNS DN, a buffer of size \fBDNS_A4RSIZE\fR (30 bytes) for
+-IPv4 address, or \fBDNS_A6RSIZE\fR (74 bytes) for IPv6 address, is sufficient.
+-.RE
+-
+-.PP
+-.nf
+-int \fBdns_dntop\fR(\fIdn\fR, \fIname\fR, \fInamesiz\fR)
+-   const unsigned char *\fIdn\fR;
+-   const char *\fIname\fR; unsigned \fInamesiz\fR;
+-.fi
+-.RS
+-convert domain name \fIdn\fR in DN format to asciiz string, placing result
+-into \fIname\fR buffer of size \fInamesiz\fR.  Maximum length of asciiz
+-representation of domain name is \fBDNS_MAXNAME\fR (1024) bytes.  Root
+-domain is represented as empty string.  Return length of the resulting name
+-(including terminating character, i.e. strlen(name)+1) on success, 0 if the
+-\fIname\fR buffer is too small, or negative value if \fIdn\fR is invalid
+-(last case should never happen since all routines in this library which
+-produce domain names ensure the DNs generated are valid).
+-.RE
+-
+-.PP
+-.nf
+-const char *\fBdns_dntosp\fR(const unsigned char *\fIdn\fR)
+-.fi
+-.RS
+-convert domain name \fIdn\fR in DN format to asciiz string using static
+-buffer.  Return the resulting asciiz string on success or NULL on failure.
+-Note since this routine uses static buffer, it is not thread-safe.
+-.RE
+-
+-.PP
+-.nf
+-unsigned \fBdns_dntop_size\fR(const unsigned char *\fIdn\fR)
+-.fi
+-.RS
+-return the buffer size needed to convert the \fIdn\fR domain name
+-in DN format to asciiz string, for \fBdns_dntop\fR().  The routine
+-return either the size of buffer required, including the trailing
+-zero byte, or 0 if \fIdn\fR is invalid.
+-.RE
+-
+-.SS "Working with DNS Packets"
+-
+-.PP
+-The following routines are provided to encode and decode DNS on-wire
+-packets.  This is low-level interface.
+-
+-.PP
+-DNS response codes (returned by \fBdns_rcode\fR() routine) are
+-defined as constants prefixed with \fBDNS_R_\fR.  See dns.h
+-header file for the complete list.  In particular, constants
+-\fBDNS_R_NOERROR\fR (0), \fBDNS_R_SERVFAIL\fR, \fBDNS_R_NXDOMAIN\fR
+-may be of interest to an application.
+-
+-.PP
+-.nf
+-unsigned \fBdns_get16\fR(const unsigned char *\fIp\fR)
+-unsigned \fBdns_get32\fR(const unsigned char *\fIp\fR)
+-.fi
+-.RS
+-helper routines, convert 16-bit or 32-bit integer in on-wire
+-format pointed to by \fIp\fR to unsigned.
+-.RE
+-
+-.PP
+-.nf
+-unsigned char *\fBdns_put16\fR(unsigned char *\fId\fR, unsigned \fIn\fR)
+-unsigned char *\fBdns_put32\fR(unsigned char *\fId\fR, unsigned \fIn\fR)
+-.fi
+-.RS
+-helper routine, convert unsigned 16-bit or 32-bit integer \fIn\fR to
+-on-wire format to buffer pointed to by \fId\fR, return \fId\fR+2 or
+-\fId\fR+4.
+-.RE
+-
+-.PP
+-.nf
+-\fBDNS_HSIZE\fR (12)
+-.fi
+-.RS
+-defines size of DNS header.  Data section
+-in the DNS packet immediately follows the header.  In the header,
+-there are query identifier (id), various flags and codes,
+-and number of resource records in various data sections.
+-See dns.h header file for complete list of DNS header definitions.
+-.RE
+-
+-.PP
+-.nf
+-unsigned \fBdns_qid\fR(const unsigned char *\fIpkt\fR)
+-int \fBdns_rd\fR(const unsigned char *\fIpkt\fR)
+-int \fBdns_tc\fR(const unsigned char *\fIpkt\fR)
+-int \fBdns_aa\fR(const unsigned char *\fIpkt\fR)
+-int \fBdns_qr\fR(const unsigned char *\fIpkt\fR)
+-int \fBdns_ra\fR(const unsigned char *\fIpkt\fR)
+-unsigned \fBdns_opcode\fR(const unsigned char *\fIpkt\fR)
+-unsigned \fBdns_rcode\fR(const unsigned char *\fIpkt\fR)
+-unsigned \fBdns_numqd\fR(const unsigned char *\fIpkt\fR)
+-unsigned \fBdns_numan\fR(const unsigned char *\fIpkt\fR)
+-unsigned \fBdns_numns\fR(const unsigned char *\fIpkt\fR)
+-unsigned \fBdns_numar\fR(const unsigned char *\fIpkt\fR)
+-const unsigned char *\fBdns_payload\fR(const unsigned char *\fIpkt\fR)
+-.fi
+-.RS
+-return various parts from the DNS packet header \fIpkt\fR:
+-query identifier (qid),
+-recursion desired (rd) flag,
+-truncation occured (tc) flag,
+-authoritative answer (aa) flag,
+-query response (qr) flag,
+-recursion available (ra) flag,
+-operation code (opcode),
+-result code (rcode),
+-number of entries in question section (numqd),
+-number of answers (numan),
+-number of authority records (numns),
+-number of additional records (numar),
+-and the pointer to the packet data (payload).
+-.RE
+-
+-.PP
+-.nf
+-int \fBdns_getdn\fR(\fIpkt\fR, \fIcurp\fR, \fIpkte\fR, \fIdn\fR, \fIdnsiz\fR)
+-const unsigned char *\fBdns_skipdn\fR(\fIcur\fR, \fIpkte\fR)
+-   const unsigned char *\fIpkt\fR, *\fIpkte\fR, **\fIcurp\fR, *\fIcur\fR;
+-   unsigned char *\fIdn\fR; unsigned \fIdnsiz\fR;
+-.fi
+-.RS
+-\fBdns_getdn\fR() extract DN from DNS packet \fIpkt\fR which ends before
+-\fIpkte\fR starting at position *\fIcurp\fR into buffer pointed to by
+-\fIdn\fR of size \fIdnsiz\fR.  Upon successeful completion, *\fIcurp\fR
+-will point to the next byte in the packet after the extracted domain name.
+-It return positive number (length of the DN if \fIdn\fR) upon successeful
+-completion, negative value on error (when the packet contains invalid data),
+-or zero if the \fIdnsiz\fR is too small (maximum length of a domain name is
+-\fBDNS_MAXDN\fR).  \fBdns_skipdn\fR() return pointer to the next byte in
+-DNS packet which ends up before \fIpkte\fR after a domain name which starts
+-at the \fIcur\fP byte, or NULL if the packet is invalid.  \fBdns_skipdn\fR()
+-is more or less equivalent to what \fBdns_getdn\fR() does, except it does not
+-actually extract the domain name in question, and uses simpler interface.
+-.RE
+-
+-.PP
+-.nf
+-struct \fBdns_rr\fR {
+-  unsigned char \fBdnsrr_dn\fR[DNS_MAXDN]; /* the RR DN name */
+-  enum dns_class \fBdnsrr_cls\fR;          /* class of the RR */
+-  enum dns_type  \fBdnsrr_typ\fR;          /* type of the RR */
+-  unsigned \fBdnsrr_ttl\fR;                /* TTL value */
+-  unsigned \fBdnsrr_dsz\fR;                /* size of data in bytes */
+-  const unsigned char *\fBdnsrr_dptr\fR;   /* pointer to the first data byte */
+-  const unsigned char *\fBdnsrr_dend\fR;   /* next byte after RR */
+-};
+-.fi
+-.RS
+-The \fBdns_rr\fR structure is used to hold information about
+-single DNS Resource Record (RR) in an easy to use form.
+-.RE
+-
+-.PP
+-.nf
+-struct \fBdns_parse\fR {
+-  const unsigned char *\fBdnsp_pkt\fR; /* pointer to the packet being parsed */
+-  const unsigned char *\fBdnsp_end\fR; /* end of the packet pointer */
+-  const unsigned char *\fBdnsp_cur\fR; /* current packet positionn */
+-  const unsigned char *\fBdnsp_ans\fR; /* pointer to the answer section */
+-  int \fBdnsp_rrl\fR;                  /* number of RRs left */
+-  int \fBdnsp_nrr\fR;                  /* number of relevant RRs seen so far */
+-  unsigned \fBdnsp_ttl\fR;             /* TTL value so far */
+-  const unsigned char *\fBdnsp_qdn\fR; /* the domain of interest or NULL */
+-  enum dns_class \fBdnsp_qcls\fR;      /* class of interest or 0 for any */
+-  enum dns_type  \fBdnsp_qtyp\fR;      /* type of interest or 0 for any */
+-  unsigned char \fBdnsp_dnbuf\fR[DNS_MAXDN]; /* domain name buffer */
+-};
+-.fi
+-.RS
+-The \fBdns_parse\fR structure is used to parse DNS reply packet.
+-It holds information about the packet being parsed (dnsp_pkt, dnsp_end and
+-dnsp_cur fields), number of RRs in the current section left to do, and
+-the information about specific RR which we're looking for (dnsp_qdn,
+-dnsp_qcls and dnsp_qtyp fields).
+-.RE
+-
+-.PP
+-.nf
+-int \fBdns_initparse\fR(struct dns_parse *\fIp\fR,
+-  const unsigned char *\fIqdn\fR,
+-  const unsigned char *\fIpkt\fR,
+-  const unsigned char *\fIcur\fR,
+-  const unsigned char *\fIend\fR)
+-.fi
+-.RS
+-initializes the RR parsing structure \fIp\fR.  Arguments \fIpkt\fR, \fIcur\fR
+-and \fIend\fR should describe the received packet: \fIpkt\fR is the start of
+-the packet, \fIend\fR points to the next byte after the end of the packet,
+-and \fIcur\fR points past the query DN in query section (to query class+type
+-information).  And \fIqdn\fR points to the query DN.  This is the arguments
+-passed to \fBdns_parse_fn\fR() routine. \fBdns_initparse\fR() initializes
+-\fBdnsp_pkt\fR, \fBdnsp_end\fR and \fBdnsp_qdn\fR fields to the corresponding
+-arguments, extracts and initializes \fBdnsp_qcls\fR and \fBdnsp_qtyp\fR
+-fields to the values found at \fIcur\fR pointer, initializes
+-\fBdnsp_cur\fR and \fBdnsp_ans\fR fields to be \fIcur\fR+4 (to the start of
+-answer section), and initializes \fBdnsp_rrl\fR field to be number of entries
+-in answer section. \fBdnsp_ttl\fR will be set to max TTL value, 0xffffffff,
+-and \fBdnsp_nrr\fR to 0.
+-.RE
+-
+-.PP
+-.nf
+-int \fBdns_nextrr\fR(struct dns_parse *\fIp\fR, struct dns_rr *\fIrr\fR);
+-.fi
+-.RS
+-searches for next RR in the packet based on the criteria provided in
+-the \fIp\fR structure, filling in the \fIrr\fR structure and
+-advancing \fIp\fR->\fBdnsp_cur\fR to the next RR in the packet.
+-RR selection is based on dnsp_qdn, dnsp_qcls and dnsp_qtyp fields in
+-the dns_parse structure.  Any (or all) of the 3 fields may be 0,
+-which means any actual value from the packet is acceptable.  In case
+-the field isn't 0 (or NULL for dnsp_qdn), only RRs with corresponding
+-characteristics are acceptable.  Additionally, when dnsp_qdn is non-NULL,
+-\fBdns_nextrr\fR() performs automatic CNAME expansion.
+-Routine will return positive value on success, 0 in case it reached the end
+-of current section in the packet (\fIp\fR->\fBdnsp_rrl\fR is zero), or
+-negative value if next RR can not be decoded (packet format is invalid).
+-The routine updates \fIp\fR->\fBdnsp_qdn\fR automatically when this
+-field is non-NULL and it encounters appropriate CNAME RRs (saving CNAME
+-target in \fIp\fR->\fBdnsp_dnbuf\fR), so after end of the process,
+-\fIp\fR->\fBdnsp_qdn\fR will point to canonical name of the domain
+-in question.  The routine updates \fIp\fR->\fBdnsp_ttl\fR value to
+-be the minimum TTL of all RRs found.
+-.RE
+-
+-.PP
+-.nf
+-void \fBdns_rewind\fR(struct dns_parse *\fIp\fR, const unsigned char *\fIqdn\fR)
+-.fi
+-.RS
+-this routine "rewinds" the packet parse state structure to be at the
+-same state as after a call to \fBdns_initparse\fR(), i.e. reposition
+-the parse structure \fIp\fR to the start of answer section and
+-initialize \fIp\fR->\fBdnsp_rrl\fR to the number of entries in
+-answer section.
+-.RE
+-
+-.PP
+-.nf
+-int \fBdns_stdrr_size\fR(const struct dns_parse *\fIp\fR);
+-.fi
+-.RS
+-return size to hold standard RRset structure information, as shown
+-in \fBdns_rr_null\fR structure (for the query and canonical
+-names).  Used to calculate amount of memory to allocate for common
+-part of type-specific RR structures in parsing routines.
+-.RE
+-
+-.PP
+-.nf
+-void *\fBdns_stdrr_finish\fR(struct dns_rr_null *\fIret\fR, char *\fIcp\fR,
+-  const struct dns_parse *\fIp\fR);
+-.fi
+-.RS
+-initializes standard RRset fields in \fIret\fR structure using buffer
+-pointed to by \fIcp\fR, which should have at least as many bytes
+-as \fBdns_stdrr_size\fR(\fIp\fR) returned.  Used to finalize common
+-part of type-specific RR structures in parsing routines.
+-.RE
+-
+-.PP
+-See library source for usage examples of all the above low-level routines,
+-especially source of the parsing routines.
+-
+-.SH AUTHOR
+-.PP
+-The \fBudns\fR library has been written by Michael Tokarev, mjt at corpit.ru.
+diff --git a/udns/source/udns.h b/udns/source/udns.h
+deleted file mode 100644
+index 7e89b85..0000000
+--- a/udns/source/udns.h
++++ /dev/null
+@@ -1,736 +0,0 @@
+-/* $Id: udns.h,v 1.41 2006/11/29 01:20:30 mjt Exp $
+-   header file for the UDNS library.
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#ifndef UDNS_VERSION	/* include guard */
+-
+-#define UDNS_VERSION "0.0.9pre"
+-
+-#ifdef WIN32
+-# ifdef UDNS_DYNAMIC_LIBRARY
+-#  ifdef DNS_LIBRARY_BUILD
+-#   define UDNS_API __declspec(dllexport)
+-#   define UDNS_DATA_API __declspec(dllexport)
+-#  else
+-#   define UDNS_API __declspec(dllimport)
+-#   define UDNS_DATA_API __declspec(dllimport)
+-#  endif
+-# endif
+-#endif
+-
+-#ifndef UDNS_API
+-# define UDNS_API
+-#endif
+-#ifndef UDNS_DATA_API
+-# define UDNS_DATA_API
+-#endif
+-
+-#include <sys/types.h>		/* for time_t */
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/* forward declarations if sockets stuff isn't #include'd */
+-struct in_addr;
+-struct in6_addr;
+-struct sockaddr;
+-
+-/**************************************************************************/
+-/**************** Common definitions **************************************/
+-
+-UDNS_API const char *
+-dns_version(void);
+-
+-struct dns_ctx;
+-struct dns_query;
+-
+-/* shorthand for [const] unsigned char */
+-typedef unsigned char dnsc_t;
+-typedef const unsigned char dnscc_t;
+-
+-#define DNS_MAXDN	255	/* max DN length */
+-#define DNS_MAXLABEL	63	/* max DN label length */
+-#define DNS_MAXNAME	1024	/* max asciiz domain name length */
+-#define DNS_HSIZE	12	/* DNS packet header size */
+-#define DNS_PORT	53	/* default domain port */
+-#define DNS_MAXSERV	6	/* max servers to consult */
+-#define DNS_MAXSRCH	5	/* max searchlist entries */
+-#define DNS_MAXPACKET	512	/* max traditional-DNS UDP packet size */
+-#define DNS_EDNS0PACKET	4096	/* EDNS0 packet size to use */
+-
+-enum dns_class {	/* DNS RR Classes */
+-  DNS_C_INVALID	= 0,	/* invalid class */
+-  DNS_C_IN	= 1,	/* Internet */
+-  DNS_C_CH	= 3,	/* CHAOS */
+-  DNS_C_HS	= 4,	/* HESIOD */
+-  DNS_C_ANY	= 255	/* wildcard */
+-};
+-
+-enum dns_type {		/* DNS RR Types */
+-  DNS_T_INVALID		= 0,	/* Cookie. */
+-  DNS_T_A		= 1,	/* Host address. */
+-  DNS_T_NS		= 2,	/* Authoritative server. */
+-  DNS_T_MD		= 3,	/* Mail destination. */
+-  DNS_T_MF		= 4,	/* Mail forwarder. */
+-  DNS_T_CNAME		= 5,	/* Canonical name. */
+-  DNS_T_SOA		= 6,	/* Start of authority zone. */
+-  DNS_T_MB		= 7,	/* Mailbox domain name. */
+-  DNS_T_MG		= 8,	/* Mail group member. */
+-  DNS_T_MR		= 9,	/* Mail rename name. */
+-  DNS_T_NULL		= 10,	/* Null resource record. */
+-  DNS_T_WKS		= 11,	/* Well known service. */
+-  DNS_T_PTR		= 12,	/* Domain name pointer. */
+-  DNS_T_HINFO		= 13,	/* Host information. */
+-  DNS_T_MINFO		= 14,	/* Mailbox information. */
+-  DNS_T_MX		= 15,	/* Mail routing information. */
+-  DNS_T_TXT		= 16,	/* Text strings. */
+-  DNS_T_RP		= 17,	/* Responsible person. */
+-  DNS_T_AFSDB		= 18,	/* AFS cell database. */
+-  DNS_T_X25		= 19,	/* X_25 calling address. */
+-  DNS_T_ISDN		= 20,	/* ISDN calling address. */
+-  DNS_T_RT		= 21,	/* Router. */
+-  DNS_T_NSAP		= 22,	/* NSAP address. */
+-  DNS_T_NSAP_PTR	= 23,	/* Reverse NSAP lookup (deprecated). */
+-  DNS_T_SIG		= 24,	/* Security signature. */
+-  DNS_T_KEY		= 25,	/* Security key. */
+-  DNS_T_PX		= 26,	/* X.400 mail mapping. */
+-  DNS_T_GPOS		= 27,	/* Geographical position (withdrawn). */
+-  DNS_T_AAAA		= 28,	/* Ip6 Address. */
+-  DNS_T_LOC		= 29,	/* Location Information. */
+-  DNS_T_NXT		= 30,	/* Next domain (security). */
+-  DNS_T_EID		= 31,	/* Endpoint identifier. */
+-  DNS_T_NIMLOC		= 32,	/* Nimrod Locator. */
+-  DNS_T_SRV		= 33,	/* Server Selection. */
+-  DNS_T_ATMA		= 34,	/* ATM Address */
+-  DNS_T_NAPTR		= 35,	/* Naming Authority PoinTeR */
+-  DNS_T_KX		= 36,	/* Key Exchange */
+-  DNS_T_CERT		= 37,	/* Certification record */
+-  DNS_T_A6		= 38,	/* IPv6 address (deprecates AAAA) */
+-  DNS_T_DNAME		= 39,	/* Non-terminal DNAME (for IPv6) */
+-  DNS_T_SINK		= 40,	/* Kitchen sink (experimentatl) */
+-  DNS_T_OPT		= 41,	/* EDNS0 option (meta-RR) */
+-  DNS_T_DS		= 43,	/* DNSSEC */
+-  DNS_T_NSEC		= 47,	/* DNSSEC */
+-  DNS_T_TSIG		= 250,	/* Transaction signature. */
+-  DNS_T_IXFR		= 251,	/* Incremental zone transfer. */
+-  DNS_T_AXFR		= 252,	/* Transfer zone of authority. */
+-  DNS_T_MAILB		= 253,	/* Transfer mailbox records. */
+-  DNS_T_MAILA		= 254,	/* Transfer mail agent records. */
+-  DNS_T_ANY		= 255,	/* Wildcard match. */
+-  DNS_T_ZXFR		= 256,	/* BIND-specific, nonstandard. */
+-  DNS_T_MAX		= 65536
+-};
+-
+-/**************************************************************************/
+-/**************** Domain Names (DNs) **************************************/
+-
+-/* return length of the DN */
+-UDNS_API unsigned
+-dns_dnlen(dnscc_t *dn);
+-
+-/* return #of labels in a DN */
+-UDNS_API unsigned
+-dns_dnlabels(dnscc_t *dn);
+-
+-/* lower- and uppercase single DN char */
+-#define DNS_DNLC(c) ((c) >= 'A' && (c) <= 'Z' ? (c) - 'A' + 'a' : (c))
+-#define DNS_DNUC(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c))
+-
+-/* compare the DNs, return dnlen of equal or 0 if not */
+-UDNS_API unsigned
+-dns_dnequal(dnscc_t *dn1, dnscc_t *dn2);
+-
+-/* copy one DN to another, size checking */
+-UDNS_API unsigned
+-dns_dntodn(dnscc_t *sdn, dnsc_t *ddn, unsigned ddnsiz);
+-
+-/* convert asciiz string of length namelen (0 to use strlen) to DN */
+-UDNS_API int
+-dns_ptodn(const char *name, unsigned namelen,
+-          dnsc_t *dn, unsigned dnsiz, int *isabs);
+-
+-/* simpler form of dns_ptodn() */
+-#define dns_sptodn(name,dn,dnsiz) dns_ptodn((name),0,(dn),(dnsiz),0)
+-
+-UDNS_DATA_API extern dnscc_t dns_inaddr_arpa_dn[14];
+-#define DNS_A4RSIZE	30
+-UDNS_API int
+-dns_a4todn(const struct in_addr *addr, dnscc_t *tdn,
+-           dnsc_t *dn, unsigned dnsiz);
+-UDNS_API int
+-dns_a4ptodn(const struct in_addr *addr, const char *tname,
+-            dnsc_t *dn, unsigned dnsiz);
+-UDNS_API dnsc_t *
+-dns_a4todn_(const struct in_addr *addr, dnsc_t *dn, dnsc_t *dne);
+-
+-UDNS_DATA_API extern dnscc_t dns_ip6_arpa_dn[10];
+-#define DNS_A6RSIZE	74
+-UDNS_API int
+-dns_a6todn(const struct in6_addr *addr, dnscc_t *tdn,
+-           dnsc_t *dn, unsigned dnsiz);
+-UDNS_API int
+-dns_a6ptodn(const struct in6_addr *addr, const char *tname,
+-            dnsc_t *dn, unsigned dnsiz);
+-UDNS_API dnsc_t *
+-dns_a6todn_(const struct in6_addr *addr, dnsc_t *dn, dnsc_t *dne);
+-
+-/* convert DN into asciiz string */
+-UDNS_API int
+-dns_dntop(dnscc_t *dn, char *name, unsigned namesiz);
+-
+-/* convert DN into asciiz string, using static buffer (NOT thread-safe!) */
+-UDNS_API const char *
+-dns_dntosp(dnscc_t *dn);
+-
+-/* return buffer size (incl. null byte) required for asciiz form of a DN */
+-UDNS_API unsigned
+-dns_dntop_size(dnscc_t *dn);
+-
+-/**************************************************************************/
+-/**************** DNS raw packet layout ***********************************/
+-
+-enum dns_rcode {	/* reply codes */
+-  DNS_R_NOERROR		= 0,	/* ok, no error */
+-  DNS_R_FORMERR		= 1,	/* format error */
+-  DNS_R_SERVFAIL	= 2,	/* server failed */
+-  DNS_R_NXDOMAIN	= 3,	/* domain does not exists */
+-  DNS_R_NOTIMPL		= 4,	/* not implemented */
+-  DNS_R_REFUSED		= 5,	/* query refused */
+-  /* these are for BIND_UPDATE */
+-  DNS_R_YXDOMAIN	= 6,	/* Name exists */
+-  DNS_R_YXRRSET		= 7,	/* RRset exists */
+-  DNS_R_NXRRSET		= 8,	/* RRset does not exist */
+-  DNS_R_NOTAUTH		= 9,	/* Not authoritative for zone */
+-  DNS_R_NOTZONE		= 10,	/* Zone of record different from zone section */
+-  /*ns_r_max = 11,*/
+-  /* The following are TSIG extended errors */
+-  DNS_R_BADSIG		= 16,
+-  DNS_R_BADKEY		= 17,
+-  DNS_R_BADTIME		= 18
+-};
+-
+-static __inline unsigned dns_get16(dnscc_t *s) {
+-  return ((unsigned)s[0]<<8) | s[1];
+-}
+-static __inline unsigned dns_get32(dnscc_t *s) {
+-  return ((unsigned)s[0]<<24) | ((unsigned)s[1]<<16)
+-        | ((unsigned)s[2]<<8) | s[3];
+-}
+-static __inline dnsc_t *dns_put16(dnsc_t *d, unsigned n) {
+-  *d++ = (n >> 8) & 255; *d++ = n & 255; return d;
+-}
+-static __inline dnsc_t *dns_put32(dnsc_t *d, unsigned n) {
+-  *d++ = (n >> 24) & 255; *d++ = (n >> 16) & 255;
+-  *d++ = (n >>  8) & 255; *d++ = n & 255;
+-  return d;
+-}
+-
+-/* DNS Header layout */
+-enum {
+- /* bytes 0:1 - query ID */
+-  DNS_H_QID1	= 0,
+-  DNS_H_QID2	= 1,
+-  DNS_H_QID	= DNS_H_QID1,
+-#define dns_qid(pkt)	dns_get16((pkt)+DNS_H_QID)
+- /* byte 2: flags1 */
+-  DNS_H_F1	= 2,
+-  DNS_HF1_QR	= 0x80,	/* query response flag */
+-#define dns_qr(pkt)	((pkt)[DNS_H_F1]&DNS_HF1_QR)
+-  DNS_HF1_OPCODE = 0x78, /* opcode, 0 = query */
+-#define dns_opcode(pkt)	(((pkt)[DNS_H_F1]&DNS_HF1_OPCODE)>>3)
+-  DNS_HF1_AA	= 0x04,	/* auth answer */
+-#define dns_aa(pkt)	((pkt)[DNS_H_F1]&DNS_HF1_AA)
+-  DNS_HF1_TC	= 0x02,	/* truncation flag */
+-#define dns_tc(pkt)	((pkt)[DNS_H_F1]&DNS_HF1_TC)
+-  DNS_HF1_RD	= 0x01,	/* recursion desired (may be set in query) */
+-#define dns_rd(pkt)	((pkt)[DNS_H_F1]&DNS_HF1_RD)
+- /* byte 3: flags2 */
+-  DNS_H_F2	= 3,
+-  DNS_HF2_RA	= 0x80,	/* recursion available */
+-#define dns_ra(pkt)	((pkt)[DNS_H_F2]&DNS_HF2_RA)
+-  DNS_HF2_Z	= 0x70,	/* reserved */
+-  DNS_HF2_RCODE	= 0x0f,	/* response code, DNS_R_XXX above */
+-#define dns_rcode(pkt)	((pkt)[DNS_H_F2]&DNS_HF2_RCODE)
+- /* bytes 4:5: qdcount, numqueries */
+-  DNS_H_QDCNT1	= 4,
+-  DNS_H_QDCNT2	= 5,
+-  DNS_H_QDCNT	= DNS_H_QDCNT1,
+-#define dns_numqd(pkt)	dns_get16((pkt)+4)
+- /* bytes 6:7: ancount, numanswers */
+-  DNS_H_ANCNT1	= 6,
+-  DNS_H_ANCNT2	= 7,
+-  DNS_H_ANCNT	= DNS_H_ANCNT1,
+-#define dns_numan(pkt)	dns_get16((pkt)+6)
+- /* bytes 8:9: nscount, numauthority */
+-  DNS_H_NSCNT1	= 8,
+-  DNS_H_NSCNT2	= 9,
+-  DNS_H_NSCNT	= DNS_H_NSCNT1,
+-#define dns_numns(pkt)	dns_get16((pkt)+8)
+- /* bytes 10:11: arcount, numadditional */
+-  DNS_H_ARCNT1	= 10,
+-  DNS_H_ARCNT2	= 11,
+-  DNS_H_ARCNT	= DNS_H_ARCNT1,
+-#define dns_numar(pkt)	dns_get16((pkt)+10)
+-#define dns_payload(pkt) ((pkt)+DNS_HSIZE)
+-};
+-
+-/* packet buffer: start at pkt, end before pkte, current pos *curp.
+- * extract a DN and set *curp to the next byte after DN in packet.
+- * return -1 on error, 0 if dnsiz is too small, or dnlen on ok.
+- */
+-UDNS_API int
+-dns_getdn(dnscc_t *pkt, dnscc_t **curp, dnscc_t *end,
+-          dnsc_t *dn, unsigned dnsiz);
+-
+-/* skip the DN at position cur in packet ending before pkte,
+- * return pointer to the next byte after the DN or NULL on error */
+-UDNS_API dnscc_t *
+-dns_skipdn(dnscc_t *end, dnscc_t *cur);
+-
+-struct dns_rr {		/* DNS Resource Record */
+-  dnsc_t dnsrr_dn[DNS_MAXDN];	/* the DN of the RR */
+-  enum dns_class dnsrr_cls;	/* Class */
+-  enum dns_type  dnsrr_typ;	/* Type */
+-  unsigned dnsrr_ttl;		/* Time-To-Live (TTL) */
+-  unsigned dnsrr_dsz;		/* data size */
+-  dnscc_t *dnsrr_dptr;		/* pointer to start of data */
+-  dnscc_t *dnsrr_dend;		/* past end of data */
+-};
+-
+-struct dns_parse {	/* RR/packet parsing state */
+-  dnscc_t *dnsp_pkt;		/* start of the packet */
+-  dnscc_t *dnsp_end;		/* end of the packet */
+-  dnscc_t *dnsp_cur;		/* current packet position */
+-  dnscc_t *dnsp_ans;		/* start of answer section */
+-  int dnsp_rrl;			/* number of RRs left to go */
+-  int dnsp_nrr;			/* RR count so far */
+-  unsigned dnsp_ttl;		/* TTL value so far */
+-  dnscc_t *dnsp_qdn;		/* the RR DN we're looking for */
+-  enum dns_class dnsp_qcls;	/* RR class we're looking for or 0 */
+-  enum dns_type  dnsp_qtyp;	/* RR type we're looking for or 0 */
+-  dnsc_t dnsp_dnbuf[DNS_MAXDN];	/* domain buffer */
+-};
+-
+-/* initialize the parse structure */
+-UDNS_API void
+-dns_initparse(struct dns_parse *p, dnscc_t *qdn,
+-              dnscc_t *pkt, dnscc_t *cur, dnscc_t *end);
+-
+-/* search next RR, <0=error, 0=no more RRs, >0 = found. */
+-UDNS_API int
+-dns_nextrr(struct dns_parse *p, struct dns_rr *rr);
+-
+-UDNS_API void
+-dns_rewind(struct dns_parse *p, dnscc_t *qdn);
+-
+-
+-/**************************************************************************/
+-/**************** Resolver Context ****************************************/
+-
+-/* default resolver context */
+-UDNS_DATA_API extern struct dns_ctx dns_defctx;
+-
+-/* initialize default resolver context and open it if do_open is true.
+- * <0 on failure. */
+-UDNS_API int
+-dns_init(int do_open);
+-
+-/* return new resolver context with the same settings as copy */
+-UDNS_API struct dns_ctx *
+-dns_new(const struct dns_ctx *copy);
+-
+-/* free resolver context; all queries are dropped */
+-UDNS_API void
+-dns_free(struct dns_ctx *ctx);
+-
+-/* add nameserver for a resolver context (or reset nslist if serv==NULL) */
+-UDNS_API int
+-dns_add_serv(struct dns_ctx *ctx, const char *serv);
+-
+-/* add nameserver using struct sockaddr array (with ports etc) */
+-UDNS_API int
+-dns_add_serv_s(struct dns_ctx *ctx, const struct sockaddr *sa);
+-
+-/* add search list element for a resolver context (or reset it if srch==NULL) */
+-UDNS_API int
+-dns_add_srch(struct dns_ctx *ctx, const char *srch);
+-
+-/* set options for a resolver context */
+-UDNS_API int
+-dns_set_opts(struct dns_ctx *ctx, const char *opts);
+-
+-enum dns_opt {		/* options */
+-  DNS_OPT_FLAGS,	/* flags, DNS_F_XXX */
+-  DNS_OPT_TIMEOUT,	/* timeout in secounds */
+-  DNS_OPT_NTRIES,	/* number of retries */
+-  DNS_OPT_NDOTS,	/* ndots */
+-  DNS_OPT_UDPSIZE,	/* EDNS0 UDP size */
+-  DNS_OPT_PORT,		/* port to use */
+-};
+-
+-/* set or get (if val<0) an option */
+-UDNS_API int
+-dns_set_opt(struct dns_ctx *ctx, enum dns_opt opt, int val);
+-
+-enum dns_flags {
+-  DNS_NOSRCH	= 0x00010000,	/* do not perform search */
+-  DNS_NORD	= 0x00020000,	/* request no recursion */
+-  DNS_AAONLY	= 0x00040000,	/* set AA flag in queries */
+-  DNS_PASSALL	= 0x00080000,	/* pass all replies to application */
+-};
+-
+-/* set the debug function pointer */
+-typedef void
+-(dns_dbgfn)(int code, const struct sockaddr *sa, unsigned salen,
+-            dnscc_t *pkt, int plen,
+-            const struct dns_query *q, void *data);
+-UDNS_API void
+-dns_set_dbgfn(struct dns_ctx *ctx, dns_dbgfn *dbgfn);
+-
+-/* open and return UDP socket */
+-UDNS_API int
+-dns_open(struct dns_ctx *ctx);
+-
+-/* return UDP socket or -1 if not open */
+-UDNS_API int
+-dns_sock(const struct dns_ctx *ctx);
+-
+-/* close the UDP socket */
+-UDNS_API void
+-dns_close(struct dns_ctx *ctx);
+-
+-/* return number of requests queued */
+-UDNS_API int
+-dns_active(const struct dns_ctx *ctx);
+-
+-/* return status of the last operation */
+-UDNS_API int
+-dns_status(const struct dns_ctx *ctx);
+-UDNS_API void
+-dns_setstatus(struct dns_ctx *ctx, int status);
+-
+-/* handle I/O event on UDP socket */
+-UDNS_API void
+-dns_ioevent(struct dns_ctx *ctx, time_t now);
+-
+-/* process any timeouts, return time in secounds to the
+- * next timeout (or -1 if none) but not greather than maxwait */
+-UDNS_API int
+-dns_timeouts(struct dns_ctx *ctx, int maxwait, time_t now);
+-
+-/* define timer requesting routine to use */
+-typedef void dns_utm_fn(struct dns_ctx *ctx, int timeout, void *data);
+-UDNS_API void
+-dns_set_tmcbck(struct dns_ctx *ctx, dns_utm_fn *fn, void *data);
+-
+-/**************************************************************************/
+-/**************** Making Queries ******************************************/
+-
+-/* query callback routine */
+-typedef void dns_query_fn(struct dns_ctx *ctx, void *result, void *data);
+-
+-/* query parse routine: raw DNS => application structure */
+-typedef int
+-dns_parse_fn(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
+-             void **res);
+-
+-enum dns_status {
+-  DNS_E_NOERROR		= 0,	/* ok, not an error */
+-  DNS_E_TEMPFAIL	= -1,	/* timeout, SERVFAIL or similar */
+-  DNS_E_PROTOCOL	= -2,	/* got garbled reply */
+-  DNS_E_NXDOMAIN	= -3,	/* domain does not exists */
+-  DNS_E_NODATA		= -4,	/* domain exists but no data of reqd type */
+-  DNS_E_NOMEM		= -5,	/* out of memory while processing */
+-  DNS_E_BADQUERY	= -6	/* the query is malformed */
+-};
+-
+-/* submit generic DN query */
+-UDNS_API struct dns_query *
+-dns_submit_dn(struct dns_ctx *ctx,
+-              dnscc_t *dn, int qcls, int qtyp, int flags,
+-              dns_parse_fn *parse, dns_query_fn *cbck, void *data);
+-/* submit generic name query */
+-UDNS_API struct dns_query *
+-dns_submit_p(struct dns_ctx *ctx,
+-             const char *name, int qcls, int qtyp, int flags,
+-             dns_parse_fn *parse, dns_query_fn *cbck, void *data);
+-
+-/* cancel the given async query in progress */
+-UDNS_API int
+-dns_cancel(struct dns_ctx *ctx, struct dns_query *q);
+-
+-/* resolve a generic query, return the answer */
+-UDNS_API void *
+-dns_resolve_dn(struct dns_ctx *ctx,
+-               dnscc_t *qdn, int qcls, int qtyp, int flags,
+-               dns_parse_fn *parse);
+-UDNS_API void *
+-dns_resolve_p(struct dns_ctx *ctx,
+-              const char *qname, int qcls, int qtyp, int flags,
+-              dns_parse_fn *parse);
+-UDNS_API void *
+-dns_resolve(struct dns_ctx *ctx, struct dns_query *q);
+-
+-
+-/* Specific RR handlers */
+-
+-#define dns_rr_common(prefix)						\
+-  char *prefix##_cname;		/* canonical name */			\
+-  char *prefix##_qname;		/* original query name */		\
+-  unsigned prefix##_ttl;	/* TTL value */				\
+-  int prefix##_nrr		/* number of records */
+-
+-struct dns_rr_null {		/* NULL RRset, aka RRset template */
+-  dns_rr_common(dnsn);
+-};
+-
+-UDNS_API int
+-dns_stdrr_size(const struct dns_parse *p);
+-UDNS_API void *
+-dns_stdrr_finish(struct dns_rr_null *ret, char *cp, const struct dns_parse *p);
+-
+-struct dns_rr_a4 {		/* the A RRset */
+-  dns_rr_common(dnsa4);
+-  struct in_addr *dnsa4_addr;	/* array of addresses, naddr elements */
+-};
+-
+-UDNS_API dns_parse_fn dns_parse_a4;	/* A RR parsing routine */
+-typedef void				/* A query callback routine */
+-dns_query_a4_fn(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data);
+-
+-/* submit A IN query */
+-UDNS_API struct dns_query *
+-dns_submit_a4(struct dns_ctx *ctx, const char *name, int flags,
+-              dns_query_a4_fn *cbck, void *data);
+-
+-/* resolve A IN query */
+-UDNS_API struct dns_rr_a4 *
+-dns_resolve_a4(struct dns_ctx *ctx, const char *name, int flags);
+-
+-
+-struct dns_rr_a6 {		/* the AAAA RRset */
+-  dns_rr_common(dnsa6);
+-  struct in6_addr *dnsa6_addr;	/* array of addresses, naddr elements */
+-};
+-
+-UDNS_API dns_parse_fn dns_parse_a6;	/* A RR parsing routine */
+-typedef void				/* A query callback routine */
+-dns_query_a6_fn(struct dns_ctx *ctx, struct dns_rr_a6 *result, void *data);
+-
+-/* submit AAAA IN query */
+-UDNS_API struct dns_query *
+-dns_submit_a6(struct dns_ctx *ctx, const char *name, int flags,
+-              dns_query_a6_fn *cbck, void *data);
+-
+-/* resolve AAAA IN query */
+-UDNS_API struct dns_rr_a6 *
+-dns_resolve_a6(struct dns_ctx *ctx, const char *name, int flags);
+-
+-
+-struct dns_rr_ptr {		/* the PTR RRset */
+-  dns_rr_common(dnsptr);
+-  char **dnsptr_ptr;		/* array of PTRs */
+-};
+-
+-UDNS_API dns_parse_fn dns_parse_ptr;	/* PTR RR parsing routine */
+-typedef void				/* PTR query callback */
+-dns_query_ptr_fn(struct dns_ctx *ctx, struct dns_rr_ptr *result, void *data);
+-/* submit PTR IN in-addr.arpa query */
+-UDNS_API struct dns_query *
+-dns_submit_a4ptr(struct dns_ctx *ctx, const struct in_addr *addr,
+-                 dns_query_ptr_fn *cbck, void *data);
+-/* resolve PTR IN in-addr.arpa query */
+-UDNS_API struct dns_rr_ptr *
+-dns_resolve_a4ptr(struct dns_ctx *ctx, const struct in_addr *addr);
+-
+-/* the same as above, but for ip6.arpa */
+-UDNS_API struct dns_query *
+-dns_submit_a6ptr(struct dns_ctx *ctx, const struct in6_addr *addr,
+-                 dns_query_ptr_fn *cbck, void *data);
+-UDNS_API struct dns_rr_ptr *
+-dns_resolve_a6ptr(struct dns_ctx *ctx, const struct in6_addr *addr);
+-
+-
+-struct dns_mx {		/* single MX RR */
+-  int priority;		/* MX priority */
+-  char *name;		/* MX name */
+-};
+-struct dns_rr_mx {		/* the MX RRset */
+-  dns_rr_common(dnsmx);
+-  struct dns_mx *dnsmx_mx;	/* array of MXes */
+-};
+-UDNS_API dns_parse_fn dns_parse_mx;	/* MX RR parsing routine */
+-typedef void				/* MX RR callback */
+-dns_query_mx_fn(struct dns_ctx *ctx, struct dns_rr_mx *result, void *data);
+-/* submit MX IN query */
+-UDNS_API struct dns_query *
+-dns_submit_mx(struct dns_ctx *ctx, const char *name, int flags,
+-              dns_query_mx_fn *cbck, void *data);
+-/* resolve MX IN query */
+-UDNS_API struct dns_rr_mx *
+-dns_resolve_mx(struct dns_ctx *ctx, const char *name, int flags);
+-
+-
+-struct dns_txt {	/* single TXT record */
+-  int len;		/* length of the text */
+-  dnsc_t *txt;	/* pointer to text buffer. May contain nulls. */
+-};
+-struct dns_rr_txt {		/* the TXT RRset */
+-  dns_rr_common(dnstxt);
+-  struct dns_txt *dnstxt_txt;	/* array of TXT records */
+-};
+-UDNS_API dns_parse_fn dns_parse_txt;	/* TXT RR parsing routine */
+-typedef void				/* TXT RR callback */
+-dns_query_txt_fn(struct dns_ctx *ctx, struct dns_rr_txt *result, void *data);
+-/* submit TXT query */
+-UDNS_API struct dns_query *
+-dns_submit_txt(struct dns_ctx *ctx, const char *name, int qcls, int flags,
+-               dns_query_txt_fn *cbck, void *data);
+-/* resolve TXT query */
+-UDNS_API struct dns_rr_txt *
+-dns_resolve_txt(struct dns_ctx *ctx, const char *name, int qcls, int flags);
+-
+-
+-struct dns_srv {	/* single SRV RR */
+-  int priority;		/* SRV priority */
+-  int weight;		/* SRV weight */
+-  int port;		/* SRV port */
+-  char *name;		/* SRV name */
+-};
+-struct dns_rr_srv {		/* the SRV RRset */
+-  dns_rr_common(dnssrv);
+-  struct dns_srv *dnssrv_srv;	/* array of SRVes */
+-};
+-UDNS_API dns_parse_fn dns_parse_srv;	/* SRV RR parsing routine */
+-typedef void				/* SRV RR callback */
+-dns_query_srv_fn(struct dns_ctx *ctx, struct dns_rr_srv *result, void *data);
+-/* submit SRV IN query */
+-UDNS_API struct dns_query *
+-dns_submit_srv(struct dns_ctx *ctx,
+-               const char *name, const char *srv, const char *proto,
+-               int flags, dns_query_srv_fn *cbck, void *data);
+-/* resolve SRV IN query */
+-UDNS_API struct dns_rr_srv *
+-dns_resolve_srv(struct dns_ctx *ctx,
+-                const char *name, const char *srv, const char *proto,
+-                int flags);
+-
+-/* NAPTR (RFC3403) RR type */
+-struct dns_naptr {	/* single NAPTR RR */
+-  int order;		/* NAPTR order */
+-  int preference;	/* NAPTR preference */
+-  char *flags;		/* NAPTR flags */
+-  char *service;	/* NAPTR service */
+-  char *regexp;		/* NAPTR regexp */
+-  char *replacement;	/* NAPTR replacement */
+-};
+-
+-struct dns_rr_naptr {		/* the NAPTR RRset */
+-  dns_rr_common(dnsnaptr);
+-  struct dns_naptr *dnsnaptr_naptr;	/* array of NAPTRes */
+-};
+-UDNS_API dns_parse_fn dns_parse_naptr;	/* NAPTR RR parsing routine */
+-typedef void				/* NAPTR RR callback */
+-dns_query_naptr_fn(struct dns_ctx *ctx,
+-                   struct dns_rr_naptr *result, void *data);
+-/* submit NAPTR IN query */
+-UDNS_API struct dns_query *
+-dns_submit_naptr(struct dns_ctx *ctx, const char *name, int flags,
+-                 dns_query_naptr_fn *cbck, void *data);
+-/* resolve NAPTR IN query */
+-UDNS_API struct dns_rr_naptr *
+-dns_resolve_naptr(struct dns_ctx *ctx, const char *name, int flags);
+-
+-
+-UDNS_API struct dns_query *
+-dns_submit_a4dnsbl(struct dns_ctx *ctx,
+-                   const struct in_addr *addr, const char *dnsbl,
+-                   dns_query_a4_fn *cbck, void *data);
+-UDNS_API struct dns_query *
+-dns_submit_a4dnsbl_txt(struct dns_ctx *ctx,
+-                       const struct in_addr *addr, const char *dnsbl,
+-                       dns_query_txt_fn *cbck, void *data);
+-UDNS_API struct dns_rr_a4 *
+-dns_resolve_a4dnsbl(struct dns_ctx *ctx,
+-                    const struct in_addr *addr, const char *dnsbl);
+-UDNS_API struct dns_rr_txt *
+-dns_resolve_a4dnsbl_txt(struct dns_ctx *ctx,
+-                        const struct in_addr *addr, const char *dnsbl);
+-
+-UDNS_API struct dns_query *
+-dns_submit_a6dnsbl(struct dns_ctx *ctx,
+-                   const struct in6_addr *addr, const char *dnsbl,
+-                   dns_query_a4_fn *cbck, void *data);
+-UDNS_API struct dns_query *
+-dns_submit_a6dnsbl_txt(struct dns_ctx *ctx,
+-                       const struct in6_addr *addr, const char *dnsbl,
+-                       dns_query_txt_fn *cbck, void *data);
+-UDNS_API struct dns_rr_a4 *
+-dns_resolve_a6dnsbl(struct dns_ctx *ctx,
+-                    const struct in6_addr *addr, const char *dnsbl);
+-UDNS_API struct dns_rr_txt *
+-dns_resolve_a6dnsbl_txt(struct dns_ctx *ctx,
+-                        const struct in6_addr *addr, const char *dnsbl);
+-
+-UDNS_API struct dns_query *
+-dns_submit_rhsbl(struct dns_ctx *ctx,
+-                 const char *name, const char *rhsbl,
+-                 dns_query_a4_fn *cbck, void *data);
+-UDNS_API struct dns_query *
+-dns_submit_rhsbl_txt(struct dns_ctx *ctx,
+-                     const char *name, const char *rhsbl,
+-                     dns_query_txt_fn *cbck, void *data);
+-UDNS_API struct dns_rr_a4 *
+-dns_resolve_rhsbl(struct dns_ctx *ctx, const char *name, const char *rhsbl);
+-UDNS_API struct dns_rr_txt *
+-dns_resolve_rhsbl_txt(struct dns_ctx *ctx, const char *name, const char *rhsbl);
+-
+-/**************************************************************************/
+-/**************** Names, Names ********************************************/
+-
+-struct dns_nameval {
+-  int val;
+-  const char *name;
+-};
+-
+-UDNS_DATA_API extern const struct dns_nameval dns_classtab[];
+-UDNS_DATA_API extern const struct dns_nameval dns_typetab[];
+-UDNS_DATA_API extern const struct dns_nameval dns_rcodetab[];
+-UDNS_API int
+-dns_findname(const struct dns_nameval *nv, const char *name);
+-#define dns_findclassname(cls) dns_findname(dns_classtab, (cls))
+-#define dns_findtypename(type) dns_findname(dns_typetab, (type))
+-#define dns_findrcodename(rcode) dns_findname(dns_rcodetab, (rcode))
+-
+-UDNS_API const char *dns_classname(enum dns_class cls);
+-UDNS_API const char *dns_typename(enum dns_type type);
+-UDNS_API const char *dns_rcodename(enum dns_rcode rcode);
+-const char *_dns_format_code(char *buf, const char *prefix, int code);
+-
+-UDNS_API const char *dns_strerror(int errnum);
+-
+-#ifdef __cplusplus
+-} /* extern "C" */
+-#endif
+-
+-#endif	/* include guard */
+diff --git a/udns/source/udns_bl.c b/udns/source/udns_bl.c
+deleted file mode 100644
+index dc6f53b..0000000
+--- a/udns/source/udns_bl.c
++++ /dev/null
+@@ -1,160 +0,0 @@
+-/* $Id: udns_bl.c,v 1.10 2005/09/12 10:55:21 mjt Exp $
+-   DNSBL stuff
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#include "udns.h"
+-#ifndef NULL
+-# define NULL 0
+-#endif
+-
+-struct dns_query *
+-dns_submit_a4dnsbl(struct dns_ctx *ctx,
+-                   const struct in_addr *addr, const char *dnsbl,
+-                   dns_query_a4_fn *cbck, void *data) {
+-  dnsc_t dn[DNS_MAXDN];
+-  if (dns_a4ptodn(addr, dnsbl, dn, sizeof(dn)) <= 0) {
+-    dns_setstatus(ctx, DNS_E_BADQUERY);
+-    return NULL;
+-  }
+-  return
+-    dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_A, DNS_NOSRCH,
+-                  dns_parse_a4, (dns_query_fn*)cbck, data);
+-}
+-
+-struct dns_query *
+-dns_submit_a4dnsbl_txt(struct dns_ctx *ctx,
+-                       const struct in_addr *addr, const char *dnsbl,
+-                       dns_query_txt_fn *cbck, void *data) {
+-  dnsc_t dn[DNS_MAXDN];
+-  if (dns_a4ptodn(addr, dnsbl, dn, sizeof(dn)) <= 0) {
+-    dns_setstatus(ctx, DNS_E_BADQUERY);
+-    return NULL;
+-  }
+-  return
+-    dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_TXT, DNS_NOSRCH,
+-                  dns_parse_txt, (dns_query_fn*)cbck, data);
+-}
+-
+-struct dns_rr_a4 *
+-dns_resolve_a4dnsbl(struct dns_ctx *ctx,
+-                    const struct in_addr *addr, const char *dnsbl) {
+-  return (struct dns_rr_a4 *)
+-    dns_resolve(ctx, dns_submit_a4dnsbl(ctx, addr, dnsbl, 0, 0));
+-}
+-
+-struct dns_rr_txt *
+-dns_resolve_a4dnsbl_txt(struct dns_ctx *ctx,
+-                        const struct in_addr *addr, const char *dnsbl) {
+-  return (struct dns_rr_txt *)
+-    dns_resolve(ctx, dns_submit_a4dnsbl_txt(ctx, addr, dnsbl, 0, 0));
+-}
+-
+-
+-struct dns_query *
+-dns_submit_a6dnsbl(struct dns_ctx *ctx,
+-                   const struct in6_addr *addr, const char *dnsbl,
+-                   dns_query_a4_fn *cbck, void *data) {
+-  dnsc_t dn[DNS_MAXDN];
+-  if (dns_a6ptodn(addr, dnsbl, dn, sizeof(dn)) <= 0) {
+-    dns_setstatus(ctx, DNS_E_BADQUERY);
+-    return NULL;
+-  }
+-  return
+-    dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_A, DNS_NOSRCH,
+-                  dns_parse_a4, (dns_query_fn*)cbck, data);
+-}
+-
+-struct dns_query *
+-dns_submit_a6dnsbl_txt(struct dns_ctx *ctx,
+-                       const struct in6_addr *addr, const char *dnsbl,
+-                       dns_query_txt_fn *cbck, void *data) {
+-  dnsc_t dn[DNS_MAXDN];
+-  if (dns_a6ptodn(addr, dnsbl, dn, sizeof(dn)) <= 0) {
+-    dns_setstatus(ctx, DNS_E_BADQUERY);
+-    return NULL;
+-  }
+-  return
+-    dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_TXT, DNS_NOSRCH,
+-                  dns_parse_txt, (dns_query_fn*)cbck, data);
+-}
+-
+-struct dns_rr_a4 *
+-dns_resolve_a6dnsbl(struct dns_ctx *ctx,
+-                    const struct in6_addr *addr, const char *dnsbl) {
+-  return (struct dns_rr_a4 *)
+-    dns_resolve(ctx, dns_submit_a6dnsbl(ctx, addr, dnsbl, 0, 0));
+-}
+-
+-struct dns_rr_txt *
+-dns_resolve_a6dnsbl_txt(struct dns_ctx *ctx,
+-                        const struct in6_addr *addr, const char *dnsbl) {
+-  return (struct dns_rr_txt *)
+-    dns_resolve(ctx, dns_submit_a6dnsbl_txt(ctx, addr, dnsbl, 0, 0));
+-}
+-
+-static int
+-dns_rhsbltodn(const char *name, const char *rhsbl, dnsc_t dn[DNS_MAXDN])
+-{
+-  int l = dns_sptodn(name, dn, DNS_MAXDN);
+-  if (l <= 0) return 0;
+-  l = dns_sptodn(rhsbl, dn+l-1, DNS_MAXDN-l+1);
+-  if (l <= 0) return 0;
+-  return 1;
+-}
+-
+-struct dns_query *
+-dns_submit_rhsbl(struct dns_ctx *ctx, const char *name, const char *rhsbl,
+-                 dns_query_a4_fn *cbck, void *data) {
+-  dnsc_t dn[DNS_MAXDN];
+-  if (!dns_rhsbltodn(name, rhsbl, dn)) {
+-    dns_setstatus(ctx, DNS_E_BADQUERY);
+-    return NULL;
+-  }
+-  return
+-    dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_A, DNS_NOSRCH,
+-                  dns_parse_a4, (dns_query_fn*)cbck, data);
+-}
+-struct dns_query *
+-dns_submit_rhsbl_txt(struct dns_ctx *ctx, const char *name, const char *rhsbl,
+-                     dns_query_txt_fn *cbck, void *data) {
+-  dnsc_t dn[DNS_MAXDN];
+-  if (!dns_rhsbltodn(name, rhsbl, dn)) {
+-    dns_setstatus(ctx, DNS_E_BADQUERY);
+-    return NULL;
+-  }
+-  return
+-    dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_TXT, DNS_NOSRCH,
+-                  dns_parse_txt, (dns_query_fn*)cbck, data);
+-}
+-
+-struct dns_rr_a4 *
+-dns_resolve_rhsbl(struct dns_ctx *ctx, const char *name, const char *rhsbl) {
+-  return (struct dns_rr_a4*)
+-    dns_resolve(ctx, dns_submit_rhsbl(ctx, name, rhsbl, 0, 0));
+-}
+-
+-struct dns_rr_txt *
+-dns_resolve_rhsbl_txt(struct dns_ctx *ctx, const char *name, const char *rhsbl)
+-{
+-  return (struct dns_rr_txt*)
+-    dns_resolve(ctx, dns_submit_rhsbl_txt(ctx, name, rhsbl, 0, 0));
+-}
+diff --git a/udns/source/udns_dn.c b/udns/source/udns_dn.c
+deleted file mode 100644
+index 1264a1d..0000000
+--- a/udns/source/udns_dn.c
++++ /dev/null
+@@ -1,382 +0,0 @@
+-/* $Id: udns_dn.c,v 1.7 2006/11/28 22:45:20 mjt Exp $
+-   domain names manipulation routines
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#include <string.h>
+-#include "udns.h"
+-
+-unsigned dns_dnlen(dnscc_t *dn) {
+-  register dnscc_t *d = dn;
+-  while(*d)
+-    d += 1 + *d;
+-  return (unsigned)(d - dn) + 1;
+-}
+-
+-unsigned dns_dnlabels(register dnscc_t *dn) {
+-  register unsigned l = 0;
+-  while(*dn)
+-    ++l, dn += 1 + *dn;
+-  return l;
+-}
+-
+-unsigned dns_dnequal(register dnscc_t *dn1, register dnscc_t *dn2) {
+-  register unsigned c;
+-  dnscc_t *dn = dn1;
+-  for(;;) {
+-    if ((c = *dn1++) != *dn2++)
+-      return 0;
+-    if (!c)
+-      return (unsigned)(dn1 - dn);
+-    while(c--) {
+-      if (DNS_DNLC(*dn1) != DNS_DNLC(*dn2))
+-        return 0;
+-      ++dn1; ++dn2;
+-    }
+-  }
+-}
+-
+-unsigned
+-dns_dntodn(dnscc_t *sdn, dnsc_t *ddn, unsigned ddnsiz) {
+-  unsigned sdnlen = dns_dnlen(sdn);
+-  if (ddnsiz < sdnlen)
+-    return 0;
+-  memcpy(ddn, sdn, sdnlen);
+-  return sdnlen;
+-}
+-
+-int
+-dns_ptodn(const char *name, unsigned namelen,
+-          dnsc_t *dn, unsigned dnsiz, int *isabs)
+-{
+-  dnsc_t *dp;		/* current position in dn (len byte first) */
+-  dnsc_t *const de	/* end of dn: last byte that can be filled up */
+-      = dn + (dnsiz >= DNS_MAXDN ? DNS_MAXDN : dnsiz) - 1;
+-  dnscc_t *np = (dnscc_t *)name;
+-  dnscc_t *ne = np + (namelen ? namelen : strlen((char*)np));
+-  dnsc_t *llab;		/* start of last label (llab[-1] will be length) */
+-  unsigned c;		/* next input character, or length of last label */
+-
+-  if (!dnsiz)
+-    return 0;
+-  dp = llab = dn + 1;
+-
+-  while(np < ne) {
+-
+-    if (*np == '.') {	/* label delimiter */
+-      c = dp - llab;		/* length of the label */
+-      if (!c) {			/* empty label */
+-        if (np == (dnscc_t *)name && np + 1 == ne) {
+-          /* special case for root dn, aka `.' */
+-          ++np;
+-          break;
+-        }
+-        return -1;		/* zero label */
+-      }
+-      if (c > DNS_MAXLABEL)
+-        return -1;		/* label too long */
+-      llab[-1] = (dnsc_t)c;	/* update len of last label */
+-      llab = ++dp; /* start new label, llab[-1] will be len of it */
+-      ++np;
+-      continue;
+-    }
+-
+-    /* check whenever we may put out one more byte */
+-    if (dp >= de) /* too long? */
+-      return dnsiz >= DNS_MAXDN ? -1 : 0;
+-    if (*np != '\\') { /* non-escape, simple case */
+-      *dp++ = *np++;
+-      continue;
+-    }
+-    /* handle \-style escape */
+-    /* note that traditionally, domain names (gethostbyname etc)
+-     * used decimal \dd notation, not octal \ooo (RFC1035), so
+-     * we're following this tradition here.
+-     */
+-    if (++np == ne)
+-      return -1;			/* bad escape */
+-    else if (*np >= '0' && *np <= '9') { /* decimal number */
+-      /* we allow not only exactly 3 digits as per RFC1035,
+-       * but also 2 or 1, for better usability. */
+-      c = *np++ - '0';
+-      if (np < ne && *np >= '0' && *np <= '9') { /* 2digits */
+-        c = c * 10 + *np++ - '0';
+-        if (np < ne && *np >= '0' && *np <= '9') {
+-          c = c * 10 + *np++ - '0';
+-          if (c > 255)
+-            return -1;			/* bad escape */
+-        }
+-      }
+-    }
+-    else
+-      c = *np++;
+-    *dp++ = (dnsc_t)c;	/* place next out byte */
+-  }
+-
+-  if ((c = dp - llab) > DNS_MAXLABEL)
+-    return -1;				/* label too long */
+-  if ((llab[-1] = (dnsc_t)c) != 0) {
+-    *dp++ = 0;
+-    if (isabs)
+-      *isabs = 0;
+-  }
+-  else if (isabs)
+-    *isabs = 1;
+-
+-  return dp - dn;
+-}
+-
+-dnscc_t dns_inaddr_arpa_dn[14] = "\07in-addr\04arpa";
+-
+-dnsc_t *
+-dns_a4todn_(const struct in_addr *addr, dnsc_t *dn, dnsc_t *dne) {
+-  dnsc_t *p;
+-  unsigned n;
+-  dnscc_t *s = ((dnscc_t *)addr) + 4;
+-  while(--s >= (dnscc_t *)addr) {
+-    n = *s;
+-    p = dn + 1;
+-    if (n > 99) {
+-      if (p + 2 > dne) return 0;
+-      *p++ = n / 100 + '0';
+-      *p++ = (n % 100 / 10) + '0';
+-      *p = n % 10 + '0';
+-    }
+-    else if (n > 9) {
+-      if (p + 1 > dne) return 0;
+-      *p++ = n / 10 + '0';
+-      *p = n % 10 + '0';
+-    }
+-    else {
+-      if (p > dne) return 0;
+-      *p = n + '0';
+-    }
+-    *dn = p - dn;
+-    dn = p + 1;
+-  }
+-  return dn;
+-}
+-
+-int dns_a4todn(const struct in_addr *addr, dnscc_t *tdn,
+-               dnsc_t *dn, unsigned dnsiz) {
+-  dnsc_t *dne = dn + (dnsiz > DNS_MAXDN ? DNS_MAXDN : dnsiz);
+-  dnsc_t *p;
+-  unsigned l;
+-  p = dns_a4todn_(addr, dn, dne);
+-  if (!p) return 0;
+-  if (!tdn)
+-    tdn = dns_inaddr_arpa_dn;
+-  l = dns_dnlen(tdn);
+-  if (p + l > dne) return dnsiz >= DNS_MAXDN ? -1 : 0;
+-  memcpy(p, tdn, l);
+-  return (p + l) - dn;
+-}
+-
+-int dns_a4ptodn(const struct in_addr *addr, const char *tname,
+-                dnsc_t *dn, unsigned dnsiz) {
+-  dnsc_t *p;
+-  int r;
+-  if (!tname)
+-    return dns_a4todn(addr, NULL, dn, dnsiz);
+-  p = dns_a4todn_(addr, dn, dn + dnsiz);
+-  if (!p) return 0;
+-  r = dns_sptodn(tname, p, dnsiz - (p - dn));
+-  return r != 0 ? r : dnsiz >= DNS_MAXDN ? -1 : 0;
+-}
+-
+-dnscc_t dns_ip6_arpa_dn[10] = "\03ip6\04arpa";
+-
+-dnsc_t *
+-dns_a6todn_(const struct in6_addr *addr, dnsc_t *dn, dnsc_t *dne) {
+-  unsigned n;
+-  dnscc_t *s = ((dnscc_t *)addr) + 16;
+-  if (dn + 64 > dne) return 0;
+-  while(--s >= (dnscc_t *)addr) {
+-    *dn++ = 1;
+-    n = *s & 0x0f;
+-    *dn++ = n > 9 ? n + 'a' - 10 : n + '0';
+-    *dn++ = 1;
+-    n = *s >> 4;
+-    *dn++ = n > 9 ? n + 'a' - 10 : n + '0';
+-  }
+-  return dn;
+-}
+-
+-int dns_a6todn(const struct in6_addr *addr, dnscc_t *tdn,
+-               dnsc_t *dn, unsigned dnsiz) {
+-  dnsc_t *dne = dn + (dnsiz > DNS_MAXDN ? DNS_MAXDN : dnsiz);
+-  dnsc_t *p;
+-  unsigned l;
+-  p = dns_a6todn_(addr, dn, dne);
+-  if (!p) return 0;
+-  if (!tdn)
+-    tdn = dns_ip6_arpa_dn;
+-  l = dns_dnlen(tdn);
+-  if (p + l > dne) return dnsiz >= DNS_MAXDN ? -1 : 0;
+-  memcpy(p, tdn, l);
+-  return (p + l) - dn;
+-}
+-
+-int dns_a6ptodn(const struct in6_addr *addr, const char *tname,
+-                dnsc_t *dn, unsigned dnsiz) {
+-  dnsc_t *p;
+-  int r;
+-  if (!tname)
+-    return dns_a6todn(addr, NULL, dn, dnsiz);
+-  p = dns_a6todn_(addr, dn, dn + dnsiz);
+-  if (!p) return 0;
+-  r = dns_sptodn(tname, p, dnsiz - (p - dn));
+-  return r != 0 ? r : dnsiz >= DNS_MAXDN ? -1 : 0;
+-}
+-
+-/* return size of buffer required to convert the dn into asciiz string.
+- * Keep in sync with dns_dntop() below.
+- */
+-unsigned dns_dntop_size(dnscc_t *dn) {
+-  unsigned size = 0;		/* the size reqd */
+-  dnscc_t *le;			/* label end */
+-
+-  while(*dn) {
+-    /* *dn is the length of the next label, non-zero */
+-    if (size)
+-      ++size;		/* for the dot */
+-    le = dn + *dn + 1;
+-    ++dn;
+-    do {
+-      switch(*dn) {
+-      case '.':
+-      case '\\':
+-      /* Special modifiers in zone files. */
+-      case '"':
+-      case ';':
+-      case '@':
+-      case '$':
+-        size += 2;
+-        break;
+-      default:
+-        if (*dn <= 0x20 || *dn >= 0x7f)
+-          /* \ddd decimal notation */
+-          size += 4;
+-        else
+-          size += 1;
+-      }
+-    } while(++dn < le);
+-  }
+-  size += 1;	/* zero byte at the end - string terminator */
+-  return size > DNS_MAXNAME ? 0 : size;
+-}
+-
+-/* Convert the dn into asciiz string.
+- * Keep in sync with dns_dntop_size() above.
+- */
+-int dns_dntop(dnscc_t *dn, char *name, unsigned namesiz) {
+-  char *np = name;			/* current name ptr */
+-  char *const ne = name + namesiz;	/* end of name */
+-  dnscc_t *le;		/* label end */
+-
+-  while(*dn) {
+-    /* *dn is the length of the next label, non-zero */
+-    if (np != name) {
+-      if (np >= ne) goto toolong;
+-      *np++ = '.';
+-    }
+-    le = dn + *dn + 1;
+-    ++dn;
+-    do {
+-      switch(*dn) {
+-      case '.':
+-      case '\\':
+-      /* Special modifiers in zone files. */
+-      case '"':
+-      case ';':
+-      case '@':
+-      case '$':
+-        if (np + 2 > ne) goto toolong;
+-        *np++ = '\\';
+-        *np++ = *dn;
+-        break;
+-      default:
+-        if (*dn <= 0x20 || *dn >= 0x7f) {
+-          /* \ddd decimal notation */
+-          if (np + 4 >= ne) goto toolong;
+-          *np++ = '\\';
+-          *np++ = '0' + (*dn / 100);
+-          *np++ = '0' + ((*dn % 100) / 10);
+-          *np++ = '0' + (*dn % 10);
+-        }
+-        else {
+-          if (np >= ne) goto toolong;
+-          *np++ = *dn;
+-        }
+-      }
+-    } while(++dn < le);
+-  }
+-  if (np >= ne) goto toolong;
+-  *np++ = '\0';
+-  return np - name;
+-toolong:
+-  return namesiz >= DNS_MAXNAME ? -1 : 0;
+-}
+-
+-#ifdef TEST
+-#include <stdio.h>
+-#include <stdlib.h>
+-
+-int main(int argc, char **argv) {
+-  int i;
+-  int sz;
+-  dnsc_t dn[DNS_MAXDN+10];
+-  dnsc_t *dl, *dp;
+-  int isabs;
+-
+-  sz = (argc > 1) ? atoi(argv[1]) : 0;
+-
+-  for(i = 2; i < argc; ++i) {
+-    int r = dns_ptodn(argv[i], 0, dn, sz, &isabs);
+-    printf("%s: ", argv[i]);
+-    if (r < 0) printf("error\n");
+-    else if (!r) printf("buffer too small\n");
+-    else {
+-      printf("len=%d dnlen=%d size=%d name:",
+-             r, dns_dnlen(dn), dns_dntop_size(dn));
+-      dl = dn;
+-      while(*dl) {
+-        printf(" %d=", *dl);
+-        dp = dl + 1;
+-        dl = dp + *dl;
+-        while(dp < dl) {
+-          if (*dp <= ' ' || *dp >= 0x7f)
+-            printf("\\%03d", *dp);
+-          else if (*dp == '.' || *dp == '\\')
+-            printf("\\%c", *dp);
+-          else
+-            putchar(*dp);
+-          ++dp;
+-        }
+-      }
+-      if (isabs) putchar('.');
+-      putchar('\n');
+-    }
+-  }
+-  return 0;
+-}
+-
+-#endif /* TEST */
+diff --git a/udns/source/udns_dntosp.c b/udns/source/udns_dntosp.c
+deleted file mode 100644
+index 933463e..0000000
+--- a/udns/source/udns_dntosp.c
++++ /dev/null
+@@ -1,30 +0,0 @@
+-/* $Id: udns_dntosp.c,v 1.5 2005/04/19 21:48:09 mjt Exp $
+-   dns_dntosp() = convert DN to asciiz string using static buffer
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#include "udns.h"
+-
+-static char name[DNS_MAXNAME];
+-
+-const char *dns_dntosp(dnscc_t *dn) {
+-  return dns_dntop(dn, name, sizeof(name)) > 0 ? name : 0;
+-}
+diff --git a/udns/source/udns_misc.c b/udns/source/udns_misc.c
+deleted file mode 100644
+index 0db7ffd..0000000
+--- a/udns/source/udns_misc.c
++++ /dev/null
+@@ -1,67 +0,0 @@
+-/* $Id: udns_misc.c,v 1.8 2005/04/05 22:51:32 mjt Exp $
+-   miscellaneous routines
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#include "udns.h"
+-
+-int dns_findname(const struct dns_nameval *nv, const char *name) {
+-  register const char *a, *b;
+-  for(; nv->name; ++nv)
+-    for(a = name, b = nv->name; ; ++a, ++b)
+-      if (DNS_DNUC(*a) != *b) break;
+-      else if (!*a) return nv->val;
+-  return -1;
+-}
+-
+-const char *_dns_format_code(char *buf, const char *prefix, int code) {
+-  char *bp = buf;
+-  unsigned c, n;
+-  do *bp++ = DNS_DNUC(*prefix);
+-  while(*++prefix);
+-  *bp++ = '#';
+-  if (code < 0) code = -code, *bp++ = '-';
+-  n = 0; c = code;
+-  do ++n;
+-  while((c /= 10));
+-  c = code;
+-  bp[n--] = '\0';
+-  do bp[n--] = c % 10 + '0';
+-  while((c /= 10));
+-  return buf;
+-}
+-
+-const char *dns_strerror(int err) {
+-  if (err >= 0) return "successeful completion";
+-  switch(err) {
+-  case DNS_E_TEMPFAIL:	return "temporary failure in name resolution";
+-  case DNS_E_PROTOCOL:	return "protocol error";
+-  case DNS_E_NXDOMAIN:	return "domain name does not exist";
+-  case DNS_E_NODATA:	return "valid domain but no data of requested type";
+-  case DNS_E_NOMEM:	return "out of memory";
+-  case DNS_E_BADQUERY:	return "malformed query";
+-  default:		return "unknown error";
+-  }
+-}
+-
+-const char *dns_version(void) {
+-  return UDNS_VERSION;
+-}
+diff --git a/udns/source/udns_parse.c b/udns/source/udns_parse.c
+deleted file mode 100644
+index 5440d92..0000000
+--- a/udns/source/udns_parse.c
++++ /dev/null
+@@ -1,169 +0,0 @@
+-/* $Id: udns_parse.c,v 1.14 2005/09/12 10:55:21 mjt Exp $
+-   raw DNS packet parsing routines
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#include <string.h>
+-#include <assert.h>
+-#include "udns.h"
+-
+-dnscc_t *dns_skipdn(dnscc_t *cur, dnscc_t *end) {
+-  unsigned c;
+-  for(;;) {
+-    if (cur >= end)
+-      return NULL;
+-    c = *cur++;
+-    if (!c)
+-      return cur;
+-    if (c & 192)		/* jump */
+-      return cur + 1 >= end ? NULL : cur + 1;
+-    cur += c;
+-  }
+-}
+-
+-int
+-dns_getdn(dnscc_t *pkt, dnscc_t **cur, dnscc_t *end,
+-          register dnsc_t *dn, unsigned dnsiz) {
+-  unsigned c;
+-  dnscc_t *pp = *cur;		/* current packet pointer */
+-  dnsc_t *dp = dn;		/* current dn pointer */
+-  dnsc_t *const de		/* end of the DN dest */
+-       = dn + (dnsiz < DNS_MAXDN ? dnsiz : DNS_MAXDN);
+-  dnscc_t *jump = NULL;		/* ptr after first jump if any */
+-  unsigned loop = 100;		/* jump loop counter */
+-
+-  for(;;) {		/* loop by labels */
+-    if (pp >= end)		/* reached end of packet? */
+-      return -1;
+-    c = *pp++;			/* length of the label */
+-    if (!c) {			/* empty label: terminate */
+-      if (dn >= de)		/* can't fit terminator */
+-        goto noroom;
+-      *dp++ = 0;
+-      /* return next pos: either after the first jump or current */
+-      *cur = jump ? jump : pp;
+-      return dp - dn;
+-    }
+-    if (c & 192) {		/* jump */
+-      if (pp >= end)		/* eop instead of jump pos */
+-        return -1;
+-      if (!jump) jump = pp + 1;	/* remember first jump */
+-      else if (!--loop) return -1; /* too many jumps */
+-      c = ((c & ~192) << 8) | *pp; /* new pos */
+-      if (c < DNS_HSIZE)	/* don't allow jump into the header */
+-        return -1;
+-      pp = pkt + c;
+-      continue;
+-    }
+-    if (c > DNS_MAXLABEL)	/* too long label? */
+-      return -1;
+-    if (pp + c > end)		/* label does not fit in packet? */
+-      return -1;
+-    if (dp + c + 1 > de)	/* if enouth room for the label */
+-      goto noroom;
+-    *dp++ = c;			/* label length */
+-    memcpy(dp, pp, c);		/* and the label itself */
+-    dp += c;
+-    pp += c;			/* advance to the next label */
+-  }
+-noroom:
+-  return dnsiz < DNS_MAXDN ? 0 : -1;
+-}
+-
+-void dns_rewind(struct dns_parse *p, dnscc_t *qdn) {
+-  p->dnsp_qdn = qdn;
+-  p->dnsp_cur = p->dnsp_ans;
+-  p->dnsp_rrl = dns_numan(p->dnsp_pkt);
+-  p->dnsp_ttl = 0xffffffffu;
+-  p->dnsp_nrr = 0;
+-}
+-
+-void
+-dns_initparse(struct dns_parse *p, dnscc_t *qdn,
+-              dnscc_t *pkt, dnscc_t *cur, dnscc_t *end) {
+-  p->dnsp_pkt = pkt;
+-  p->dnsp_end = end;
+-  p->dnsp_rrl = dns_numan(pkt);
+-  p->dnsp_qdn = qdn;
+-  assert(cur + 4 <= end);
+-  if ((p->dnsp_qtyp = dns_get16(cur+0)) == DNS_T_ANY) p->dnsp_qtyp = 0;
+-  if ((p->dnsp_qcls = dns_get16(cur+2)) == DNS_C_ANY) p->dnsp_qcls = 0;
+-  p->dnsp_cur = p->dnsp_ans = cur + 4;
+-  p->dnsp_ttl = 0xffffffffu;
+-  p->dnsp_nrr = 0;
+-}
+-
+-int dns_nextrr(struct dns_parse *p, struct dns_rr *rr) {
+-  dnscc_t *cur = p->dnsp_cur;
+-  while(p->dnsp_rrl > 0) {
+-    --p->dnsp_rrl;
+-    if (dns_getdn(p->dnsp_pkt, &cur, p->dnsp_end,
+-                  rr->dnsrr_dn, sizeof(rr->dnsrr_dn)) <= 0)
+-      return -1;
+-    if (cur + 10 > p->dnsp_end)
+-      return -1;
+-    rr->dnsrr_typ = dns_get16(cur);
+-    rr->dnsrr_cls = dns_get16(cur+2);
+-    rr->dnsrr_ttl = dns_get32(cur+4);
+-    rr->dnsrr_dsz = dns_get16(cur+8);
+-    rr->dnsrr_dptr = cur = cur + 10;
+-    rr->dnsrr_dend = cur = cur + rr->dnsrr_dsz;
+-    if (cur > p->dnsp_end)
+-      return -1;
+-    if (p->dnsp_qdn && !dns_dnequal(p->dnsp_qdn, rr->dnsrr_dn))
+-      continue;
+-    if ((!p->dnsp_qcls || p->dnsp_qcls == rr->dnsrr_cls) &&
+-        (!p->dnsp_qtyp || p->dnsp_qtyp == rr->dnsrr_typ)) {
+-      p->dnsp_cur = cur;
+-      ++p->dnsp_nrr;
+-      if (p->dnsp_ttl > rr->dnsrr_ttl) p->dnsp_ttl = rr->dnsrr_ttl;
+-      return 1;
+-    }
+-    if (p->dnsp_qdn && rr->dnsrr_typ == DNS_T_CNAME && !p->dnsp_nrr) {
+-      if (dns_getdn(p->dnsp_pkt, &rr->dnsrr_dptr, p->dnsp_end,
+-                    p->dnsp_dnbuf, sizeof(p->dnsp_dnbuf)) <= 0 ||
+-          rr->dnsrr_dptr != rr->dnsrr_dend)
+-        return -1;
+-      p->dnsp_qdn = p->dnsp_dnbuf;
+-      if (p->dnsp_ttl > rr->dnsrr_ttl) p->dnsp_ttl = rr->dnsrr_ttl;
+-    }
+-  }
+-  p->dnsp_cur = cur;
+-  return 0;
+-}
+-
+-int dns_stdrr_size(const struct dns_parse *p) {
+-  return
+-    dns_dntop_size(p->dnsp_qdn) +
+-    (p->dnsp_qdn == dns_payload(p->dnsp_pkt) ? 0 :
+-     dns_dntop_size(dns_payload(p->dnsp_pkt)));
+-}
+-
+-void *dns_stdrr_finish(struct dns_rr_null *ret, char *cp,
+-                       const struct dns_parse *p) {
+-  cp += dns_dntop(p->dnsp_qdn, (ret->dnsn_cname = cp), DNS_MAXNAME);
+-  if (p->dnsp_qdn == dns_payload(p->dnsp_pkt))
+-    ret->dnsn_qname = ret->dnsn_cname;
+-  else
+-    dns_dntop(dns_payload(p->dnsp_pkt), (ret->dnsn_qname = cp), DNS_MAXNAME);
+-  ret->dnsn_ttl = p->dnsp_ttl;
+-  return ret;
+-}
+diff --git a/udns/source/udns_resolver.c b/udns/source/udns_resolver.c
+deleted file mode 100644
+index 37c8192..0000000
+--- a/udns/source/udns_resolver.c
++++ /dev/null
+@@ -1,1342 +0,0 @@
+-/* $Id: udns_resolver.c,v 1.57 2006/11/29 01:17:43 mjt Exp $
+-   resolver stuff (main module)
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#ifdef HAVE_CONFIG_H
+-# include <config.h>
+-#endif
+-#ifdef WIN32
+-# include <winsock2.h>          /* includes <windows.h> */
+-# include <ws2tcpip.h>          /* needed for struct in6_addr */
+-# include <iphlpapi.h>		/* for dns server addresses etc */
+-# undef HAVE_POLL
+-#else
+-# include <sys/types.h>
+-# include <sys/socket.h>
+-# include <netinet/in.h>
+-# include <arpa/inet.h>		/* for inet_pton() */
+-# include <unistd.h>
+-# include <fcntl.h>
+-# include <sys/time.h>
+-# ifdef HAVE_POLL
+-#  include <sys/poll.h>
+-# endif
+-# define closesocket(sock) close(sock)
+-#endif	/* !WIN32 */
+-
+-#include <stdlib.h>
+-#include <string.h>
+-#include <time.h>
+-#include <errno.h>
+-#include <assert.h>
+-#include <stddef.h>
+-#include "udns.h"
+-
+-#define DNS_QEXTRA	16	/* size of extra buffer space */
+-#define DNS_QBUF	DNS_HSIZE+DNS_MAXDN+DNS_QEXTRA
+-
+-#if !defined(HAVE_INET6) && defined(AF_INET6)
+-# define HAVE_INET6 1
+-#endif
+-#ifdef NO_INET6
+-# undef HAVE_INET6
+-#endif
+-
+-#ifndef EAFNOSUPPORT
+-# define EAFNOSUPPORT EINVAL
+-#endif
+-
+-union sockaddr_ns {
+-  struct sockaddr sa;
+-  struct sockaddr_in sin;
+-#if HAVE_INET6
+-  struct sockaddr_in6 sin6;
+-#endif
+-};
+-
+-struct dns_qlink {
+-  struct dns_query *next, *prev;
+-};
+-
+-struct dns_query {
+-  struct dns_qlink dnsq_link;		/* list entry (should be first) */
+-  dnsc_t dnsq_buf[DNS_QBUF];		/* the query buffer */
+-  enum dns_class dnsq_cls;		/* requested RR class */
+-  enum dns_type  dnsq_typ;		/* requested RR type */
+-  unsigned dnsq_len;			/* length of the query packet */
+-  unsigned dnsq_origdnl;		/* original length of the dnsq_dn */
+-  unsigned dnsq_flags;			/* control flags for this query */
+-  unsigned dnsq_servi;			/* index of next server to try */
+-  unsigned dnsq_servwait;		/* bitmask: servers left to wait */
+-  unsigned dnsq_servskip;		/* bitmask: servers to skip */
+-  unsigned dnsq_try;			/* number of tries made so far */
+-  unsigned dnsq_srchi;			/* current search index */
+-  time_t dnsq_deadline;			/* when current try will expire */
+-  dns_parse_fn *dnsq_parse;		/* parse: raw => application */
+-  dns_query_fn *dnsq_cbck;		/* the callback to call when done */
+-  void *dnsq_cbdata;			/* user data for the callback */
+-#ifndef NDEBUG
+-  struct dns_ctx *dnsq_ctx;		/* the resolver context */
+-#endif
+-};
+-
+-/* working with dns_query lists */
+-
+-static __inline void qlist_init(struct dns_qlink *list) {
+-  list->next = list->prev = (struct dns_query *)list;
+-}
+-
+-static __inline int qlist_empty(const struct dns_qlink *list) {
+-  return list->next == (const struct dns_query *)list ? 1 : 0;
+-}
+-
+-static __inline struct dns_query *qlist_first(struct dns_qlink *list) {
+-  return list->next == (struct dns_query *)list ? 0 : list->next;
+-}
+-
+-static __inline void qlist_remove(struct dns_query *q) {
+-  q->dnsq_link.next->dnsq_link.prev = q->dnsq_link.prev;
+-  q->dnsq_link.prev->dnsq_link.next = q->dnsq_link.next;
+-}
+-
+-static __inline struct dns_query *qlist_pop(struct dns_qlink *list) {
+-  struct dns_query *q = list->next;
+-  if (q == (struct dns_query *)list)
+-    return NULL;
+-  qlist_remove(q);
+-  return q;
+-}
+-
+-/* insert q between prev and next */
+-static __inline void
+-qlist_insert(struct dns_query *q,
+-             struct dns_query *prev, struct dns_query *next) {
+-  q->dnsq_link.next = next;
+-  q->dnsq_link.prev = prev;
+-  prev->dnsq_link.next = next->dnsq_link.prev = q;
+-}
+-
+-static __inline void
+-qlist_insert_after(struct dns_query *q, struct dns_query *prev) {
+-  qlist_insert(q, prev, prev->dnsq_link.next);
+-}
+-
+-static __inline void
+-qlist_insert_before(struct dns_query *q, struct dns_query *next) {
+-  qlist_insert(q, next->dnsq_link.prev, next);
+-}
+-
+-static __inline void
+-qlist_add_tail(struct dns_query *q, struct dns_qlink *top) {
+-  qlist_insert_before(q, (struct dns_query *)top);
+-}
+-
+-static __inline void
+-qlist_add_head(struct dns_query *q, struct dns_qlink *top) {
+-  qlist_insert_after(q, (struct dns_query *)top);
+-}
+-
+-#define QLIST_FIRST(list, direction) ((list)->direction)
+-#define QLIST_ISLAST(list, q) ((q) == (struct dns_query*)(list))
+-#define QLIST_NEXT(q, direction) ((q)->dnsq_link.direction)
+-
+-#define QLIST_FOR_EACH(list, q, direction) \
+-  for(q = QLIST_FIRST(list, direction); \
+-      !QLIST_ISLAST(list, q); q = QLIST_NEXT(q, direction))
+-
+-struct dns_ctx {		/* resolver context */
+-  /* settings */
+-  unsigned dnsc_flags;			/* various flags */
+-  unsigned dnsc_timeout;		/* timeout (base value) for queries */
+-  unsigned dnsc_ntries;			/* number of retries */
+-  unsigned dnsc_ndots;			/* ndots to assume absolute name */
+-  unsigned dnsc_port;			/* default port (DNS_PORT) */
+-  unsigned dnsc_udpbuf;			/* size of UDP buffer */
+-  /* array of nameserver addresses */
+-  union sockaddr_ns dnsc_serv[DNS_MAXSERV];
+-  unsigned dnsc_nserv;			/* number of nameservers */
+-  unsigned dnsc_salen;			/* length of socket addresses */
+-  /* search list for unqualified names */
+-  dnsc_t dnsc_srch[DNS_MAXSRCH][DNS_MAXDN];
+-  unsigned dnsc_nsrch;			/* number of srch[] */
+-
+-  dns_utm_fn *dnsc_utmfn;		/* register/cancel timer events */
+-  void *dnsc_utmctx;			/* user timer context for utmfn() */
+-  time_t dnsc_utmexp;			/* when user timer expires */
+-
+-  dns_dbgfn *dnsc_udbgfn;		/* debugging function */
+-
+-  /* dynamic data */
+-  unsigned short dnsc_nextid;		/* next queue ID to use */
+-  int dnsc_udpsock;			/* UDP socket */
+-  struct dns_qlink dnsc_qactive;	/* active list sorted by deadline */
+-  int dnsc_nactive;			/* number entries in dnsc_qactive */
+-  dnsc_t *dnsc_pbuf;			/* packet buffer (udpbuf size) */
+-  int dnsc_qstatus;			/* last query status value */
+-};
+-
+-static const struct {
+-  const char *name;
+-  enum dns_opt opt;
+-  unsigned offset;
+-  unsigned min, max;
+-} dns_opts[] = {
+-#define opt(name,opt,field,min,max) \
+-	{name,opt,offsetof(struct dns_ctx,field),min,max}
+-  opt("retrans", DNS_OPT_TIMEOUT, dnsc_timeout, 1,300),
+-  opt("timeout", DNS_OPT_TIMEOUT, dnsc_timeout, 1,300),
+-  opt("retry",    DNS_OPT_NTRIES, dnsc_ntries, 1,50),
+-  opt("attempts", DNS_OPT_NTRIES, dnsc_ntries, 1,50),
+-  opt("ndots", DNS_OPT_NDOTS, dnsc_ndots, 0,1000),
+-  opt("port", DNS_OPT_PORT, dnsc_port, 1,0xffff),
+-  opt("udpbuf", DNS_OPT_UDPSIZE, dnsc_udpbuf, DNS_MAXPACKET,65536),
+-#undef opt
+-};
+-#define dns_ctxopt(ctx,offset) (*((unsigned*)(((char*)ctx)+offset)))
+-
+-#define ISSPACE(x) (x == ' ' || x == '\t' || x == '\r' || x == '\n')
+-
+-static const char space[] = " \t\r\n";
+-
+-struct dns_ctx dns_defctx;
+-
+-#define SETCTX(ctx) if (!ctx) ctx = &dns_defctx
+-#define SETCTXINITED(ctx) SETCTX(ctx); assert(CTXINITED(ctx))
+-#define CTXINITED(ctx) (ctx->dnsc_flags & DNS_INITED)
+-#define SETCTXFRESH(ctx) SETCTXINITED(ctx); assert(!CTXOPEN(ctx))
+-#define SETCTXINACTIVE(ctx) SETCTXINITED(ctx); assert(qlist_empty(&ctx->dnsc_qactive))
+-#define SETCTXOPEN(ctx) SETCTXINITED(ctx); assert(CTXOPEN(ctx))
+-#define CTXOPEN(ctx) (ctx->dnsc_udpsock >= 0)
+-
+-#if defined(NDEBUG) || !defined(DEBUG)
+-#define dns_assert_ctx(ctx)
+-#else
+-static void dns_assert_ctx(const struct dns_ctx *ctx) {
+-  int nactive = 0;
+-  const struct dns_query *q;
+-  QLIST_FOR_EACH(&ctx->dnsc_qactive, q, next) {
+-    assert(q->dnsq_ctx == ctx);
+-    assert(q->dnsq_link.next->dnsq_link.prev == q);
+-    assert(q->dnsq_link.prev->dnsq_link.next == q);
+-    ++nactive;
+-  }
+-  assert(nactive == ctx->dnsc_nactive);
+-}
+-#endif
+-
+-enum {
+-  DNS_INTERNAL		= 0xffff, /* internal flags mask */
+-  DNS_INITED		= 0x0001, /* the context is initialized */
+-  DNS_ASIS_DONE		= 0x0002, /* search: skip the last as-is query */
+-  DNS_SEEN_NODATA	= 0x0004, /* search: NODATA has been received */
+-  DNS_SEEN_FAIL		= 0x0008, /* search: SERVFAIL has been received */
+-  DNS_SEEN_WRONG	= 0x0010, /* search: something wrong happened */
+-};
+-
+-static int dns_add_serv_internal(struct dns_ctx *ctx, const char *serv) {
+-  union sockaddr_ns *sns;
+-  if (!serv)
+-    return (ctx->dnsc_nserv = 0);
+-  if (ctx->dnsc_nserv >= DNS_MAXSERV)
+-    return errno = ENFILE, -1;
+-  sns = &ctx->dnsc_serv[ctx->dnsc_nserv];
+-  memset(sns, 0, sizeof(*sns));
+-#if HAVE_INET6
+-  { struct in_addr addr;
+-    struct in6_addr addr6;
+-    if (inet_pton(AF_INET, serv, &addr) > 0) {
+-      sns->sin.sin_family = AF_INET;
+-      sns->sin.sin_addr = addr;
+-      return ++ctx->dnsc_nserv;
+-    }
+-    if (inet_pton(AF_INET6, serv, &addr6) > 0) {
+-      sns->sin6.sin6_family = AF_INET6;
+-      sns->sin6.sin6_addr = addr6;
+-      return ++ctx->dnsc_nserv;
+-    }
+-  }
+-#else
+-  { struct in_addr addr;
+-    if (inet_aton(serv, &addr) > 0) {
+-      sns->sin.sin_family = AF_INET;
+-      sns->sin.sin_addr = addr;
+-      return ++ctx->dnsc_nserv;
+-    }
+-  }
+-#endif
+-  errno = EINVAL;
+-  return -1;
+-}
+-
+-int dns_add_serv(struct dns_ctx *ctx, const char *serv) {
+-  SETCTXFRESH(ctx);
+-  return dns_add_serv_internal(ctx, serv);
+-}
+-
+-static void dns_set_serv_internal(struct dns_ctx *ctx, char *serv) {
+-  ctx->dnsc_nserv = 0;
+-  for(serv = strtok(serv, space); serv; serv = strtok(NULL, space))
+-    dns_add_serv_internal(ctx, serv);
+-}
+-
+-static int
+-dns_add_serv_s_internal(struct dns_ctx *ctx, const struct sockaddr *sa) {
+-  if (!sa)
+-    return (ctx->dnsc_nserv = 0);
+-  if (ctx->dnsc_nserv >= DNS_MAXSERV)
+-    return errno = ENFILE, -1;
+-#if HAVE_INET6
+-  else if (sa->sa_family == AF_INET6)
+-    ctx->dnsc_serv[ctx->dnsc_nserv].sin6 = *(struct sockaddr_in6*)sa;
+-#endif
+-  else if (sa->sa_family == AF_INET)
+-    ctx->dnsc_serv[ctx->dnsc_nserv].sin = *(struct sockaddr_in*)sa;
+-  else
+-    return errno = EAFNOSUPPORT, -1;
+-  return ++ctx->dnsc_nserv;
+-}
+-
+-int dns_add_serv_s(struct dns_ctx *ctx, const struct sockaddr *sa) {
+-  SETCTXFRESH(ctx);
+-  return dns_add_serv_s_internal(ctx, sa);
+-}
+-
+-static void dns_set_opts_internal(struct dns_ctx *ctx, const char *opts) {
+-  unsigned i, v;
+-  for(;;) {
+-    while(ISSPACE(*opts)) ++opts;
+-    if (!*opts) break;
+-    for(i = 0; i < sizeof(dns_opts)/sizeof(dns_opts[0]); ++i) {
+-      v = strlen(dns_opts[i].name);
+-      if (strncmp(dns_opts[i].name, opts, v) != 0 ||
+-          (opts[v] != ':' && opts[v] != '='))
+-        continue;
+-      opts += v + 1;
+-      v = 0;
+-      if (*opts < '0' || *opts > '9') break;
+-      do v = v * 10 + (*opts++ - '0');
+-      while (*opts >= '0' && *opts <= '9');
+-      if (dns_opts[i].min && v < dns_opts[i].min) v = dns_opts[i].min;
+-      else if (v > dns_opts[i].max) v = dns_opts[i].max;
+-      dns_ctxopt(ctx, dns_opts[i].offset) = v;
+-      break;
+-    }
+-    while(*opts && !ISSPACE(*opts)) ++opts;
+-  }
+-}
+-
+-int dns_set_opts(struct dns_ctx *ctx, const char *opts) {
+-  SETCTXINACTIVE(ctx);
+-  dns_set_opts_internal(ctx, opts);
+-  return 0;
+-}
+-
+-int dns_set_opt(struct dns_ctx *ctx, enum dns_opt opt, int val) {
+-  int prev;
+-  unsigned i;
+-  SETCTXINACTIVE(ctx);
+-  for(i = 0; i < sizeof(dns_opts)/sizeof(dns_opts[0]); ++i) {
+-    if (dns_opts[i].opt != opt) continue;
+-    prev = dns_ctxopt(ctx, dns_opts[i].offset);
+-    if (val >= 0) {
+-      unsigned v = val;
+-      if (v < dns_opts[i].min || v > dns_opts[i].max) {
+-        errno = EINVAL;
+-        return -1;
+-      }
+-      dns_ctxopt(ctx, dns_opts[i].offset) = v;
+-    }
+-    return prev;
+-  }
+-  if (opt == DNS_OPT_FLAGS) {
+-    prev = ctx->dnsc_flags & ~DNS_INTERNAL;
+-    if (val >= 0)
+-      ctx->dnsc_flags =
+-        (ctx->dnsc_flags & DNS_INTERNAL) | (val & ~DNS_INTERNAL);
+-    return prev;
+-  }
+-  errno = ENOSYS;
+-  return -1;
+-}
+-
+-static int dns_add_srch_internal(struct dns_ctx *ctx, const char *srch) {
+-  if (!srch)
+-    return (ctx->dnsc_nsrch = 0);
+-  else if (ctx->dnsc_nsrch >= DNS_MAXSRCH)
+-    return errno = ENFILE, -1;
+-  else if (dns_sptodn(srch, ctx->dnsc_srch[ctx->dnsc_nsrch], DNS_MAXDN) <= 0)
+-    return errno = EINVAL, -1;
+-  else
+-    return ++ctx->dnsc_nsrch;
+-}
+-
+-int dns_add_srch(struct dns_ctx *ctx, const char *srch) {
+-  SETCTXINACTIVE(ctx);
+-  return dns_add_srch_internal(ctx, srch);
+-}
+-
+-static void dns_set_srch_internal(struct dns_ctx *ctx, char *srch) {
+-  ctx->dnsc_nsrch = 0;
+-  for(srch = strtok(srch, space); srch; srch = strtok(NULL, space))
+-    dns_add_srch_internal(ctx, srch);
+-}
+-
+-static void dns_drop_utm(struct dns_ctx *ctx) {
+-  if (ctx->dnsc_utmfn)
+-    ctx->dnsc_utmfn(NULL, -1, ctx->dnsc_utmctx);
+-  ctx->dnsc_utmctx = NULL;
+-  ctx->dnsc_utmexp = -1;
+-}
+-
+-static void
+-dns_request_utm(struct dns_ctx *ctx, time_t now) {
+-  struct dns_query *q;
+-  time_t deadline;
+-  int timeout;
+-  if (!ctx->dnsc_utmfn)
+-    return;
+-  q = QLIST_FIRST(&ctx->dnsc_qactive, next);
+-  if (QLIST_ISLAST(&ctx->dnsc_qactive, q))
+-    deadline = -1, timeout = -1;
+-  else if (!now || q->dnsq_deadline <= now)
+-    deadline = 0, timeout = 0;
+-  else
+-    deadline = q->dnsq_deadline, timeout = deadline - now;
+-  if (ctx->dnsc_utmexp == deadline)
+-    return;
+-  ctx->dnsc_utmfn(ctx, timeout, ctx->dnsc_utmctx);
+-  ctx->dnsc_utmexp = deadline;
+-}
+-
+-void dns_set_dbgfn(struct dns_ctx *ctx, dns_dbgfn *dbgfn) {
+-  SETCTXINITED(ctx);
+-  ctx->dnsc_udbgfn = dbgfn;
+-}
+-
+-void
+-dns_set_tmcbck(struct dns_ctx *ctx, dns_utm_fn *fn, void *data) {
+-  SETCTXINITED(ctx);
+-  dns_drop_utm(ctx);
+-  ctx->dnsc_utmfn = fn;
+-  ctx->dnsc_utmctx = data;
+-}
+-
+-static void dns_firstid(struct dns_ctx *ctx) {
+-  struct timeval tv;
+-  gettimeofday(&tv, NULL);
+-  ctx->dnsc_nextid = (tv.tv_usec ^ getpid()) & 0xffff;
+-}
+-
+-#ifdef WIN32
+-
+-#ifndef NO_IPHLPAPI
+-
+-typedef DWORD (WINAPI *GetAdaptersAddressesFunc)(
+-  ULONG Family, DWORD Flags, PVOID Reserved,
+-  PIP_ADAPTER_ADDRESSES pAdapterAddresses,
+-  PULONG pOutBufLen);
+-
+-static int dns_initns_iphlpapi(struct dns_ctx *ctx) {
+-  HANDLE h_iphlpapi;
+-  GetAdaptersAddressesFunc pfnGetAdAddrs;
+-  PIP_ADAPTER_ADDRESSES pAddr, pAddrBuf;
+-  PIP_ADAPTER_DNS_SERVER_ADDRESS pDnsAddr;
+-  ULONG ulOutBufLen;
+-  DWORD dwRetVal;
+-  int ret = -1;
+-
+-  h_iphlpapi = LoadLibrary("iphlpapi.dll");
+-  if (!h_iphlpapi)
+-    return -1;
+-  pfnGetAdAddrs = (GetAdaptersAddressesFunc)
+-    GetProcAddress(h_iphlpapi, "GetAdaptersAddresses");
+-  if (!pfnGetAdAddrs) goto freelib;
+-  ulOutBufLen = 0;
+-  dwRetVal = pfnGetAdAddrs(AF_UNSPEC, 0, NULL, NULL, &ulOutBufLen);
+-  if (dwRetVal != ERROR_BUFFER_OVERFLOW) goto freelib;
+-  pAddrBuf = malloc(ulOutBufLen);
+-  if (!pAddrBuf) goto freelib;
+-  dwRetVal = pfnGetAdAddrs(AF_UNSPEC, 0, NULL, pAddrBuf, &ulOutBufLen);
+-  if (dwRetVal != ERROR_SUCCESS) goto freemem;
+-  for (pAddr = pAddrBuf;
+-       pAddr && ctx->dnsc_nserv <= DNS_MAXSERV;
+-       pAddr = pAddr->Next)
+-    for (pDnsAddr = pAddr->FirstDnsServerAddress;
+-         pDnsAddr && ctx->dnsc_nserv <= DNS_MAXSERV;
+-         pDnsAddr = pDnsAddr->Next)
+-      dns_add_serv_s_internal(ctx, pDnsAddr->Address.lpSockaddr);
+-  ret = 0;
+-freemem:
+-  free(pAddrBuf);
+-freelib:
+-  FreeLibrary(h_iphlpapi);
+-  return ret;
+-}
+-
+-#endif	/* !NO_IPHLPAPI */
+-
+-static int dns_initns_registry(struct dns_ctx *ctx) {
+-  LONG res;
+-  HKEY hk;
+-  DWORD type = REG_EXPAND_SZ | REG_SZ;
+-  DWORD len;
+-  char valBuf[1024];
+-
+-#define REGKEY_WINNT "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"
+-#define REGKEY_WIN9x "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP"
+-  res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WINNT, 0, KEY_QUERY_VALUE, &hk);
+-  if (res != ERROR_SUCCESS)
+-    res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WIN9x,
+-                       0, KEY_QUERY_VALUE, &hk);
+-  if (res != ERROR_SUCCESS)
+-    return -1;
+-  len = sizeof(valBuf) - 1;
+-  res = RegQueryValueEx(hk, "NameServer", NULL, &type, valBuf, &len);
+-  if (res != ERROR_SUCCESS || !len || !valBuf[0]) {
+-    len = sizeof(valBuf) - 1;
+-    res = RegQueryValueEx(hk, "DhcpNameServer", NULL, &type, valBuf, &len);
+-  }
+-  RegCloseKey(hk);
+-  if (res != ERROR_SUCCESS || !len || !valBuf[0])
+-    return -1;
+-  valBuf[len] = '\0';
+-  /* nameservers are stored as a whitespace-seperate list:
+-   * "192.168.1.1 123.21.32.12" */
+-  dns_set_serv_internal(ctx, valBuf);
+-  return 0;
+-}
+-
+-static int dns_init_internal(struct dns_ctx *ctx) {
+-#ifndef NO_IPHLPAPI
+-  if (dns_initns_iphlpapi(ctx) == 0)
+-    return 0;
+-#endif
+-
+-  dns_initns_registry(ctx);
+-  /*XXX WIN32: probably good to get default domain and search list too...
+-   * And options.  Something is in registry. */
+-  /*XXX WIN32: maybe environment variables are also useful? */
+-  return 0;
+-}
+-
+-#else /* !WIN32 */
+-
+-static int dns_init_internal(struct dns_ctx *ctx) {
+-  char *v;
+-  char buf[2049];	/* this buffer is used to hold /etc/resolv.conf */
+-
+-  /* read resolv.conf... */
+-  { int fd = open("/etc/resolv.conf", O_RDONLY);
+-    if (fd >= 0) {
+-      int l = read(fd, buf, sizeof(buf) - 1);
+-      close(fd);
+-      buf[l < 0 ? 0 : l] = '\0';
+-    }
+-    else
+-      buf[0] = '\0';
+-  }
+-  if (buf[0]) {	/* ...and parse it */
+-    char *line, *nextline;
+-    line = buf;
+-    do {
+-      nextline = strchr(line, '\n');
+-      if (nextline) *nextline++ = '\0';
+-      v = line;
+-      while(*v && !ISSPACE(*v)) ++v;
+-      if (!*v) continue;
+-      *v++ = '\0';
+-      while(ISSPACE(*v)) ++v;
+-      if (!*v) continue;
+-      if (strcmp(line, "domain") == 0)
+-        dns_set_srch_internal(ctx, strtok(v, space));
+-      else if (strcmp(line, "search") == 0)
+-        dns_set_srch_internal(ctx, v);
+-      else if (strcmp(line, "nameserver") == 0)
+-        dns_add_serv_internal(ctx, strtok(v, space));
+-      else if (strcmp(line, "options") == 0)
+-        dns_set_opts_internal(ctx, v);
+-    } while((line = nextline) != NULL);
+-  }
+-
+-  buf[sizeof(buf)-1] = '\0';
+-
+-  /* get list of nameservers from env. vars. */
+-  if ((v = getenv("NSCACHEIP")) != NULL ||
+-      (v = getenv("NAMESERVERS")) != NULL) {
+-    strncpy(buf, v, sizeof(buf) - 1);
+-    dns_set_serv_internal(ctx, buf);
+-  }
+-  /* if $LOCALDOMAIN is set, use it for search list */
+-  if ((v = getenv("LOCALDOMAIN")) != NULL) {
+-    strncpy(buf, v, sizeof(buf) - 1);
+-    dns_set_srch_internal(ctx, buf);
+-  }
+-  if ((v = getenv("RES_OPTIONS")) != NULL)
+-    dns_set_opts_internal(ctx, v);
+-
+-  /* if still no search list, use local domain name */
+-  if (!ctx->dnsc_nsrch &&
+-      gethostname(buf, sizeof(buf) - 1) == 0 &&
+-      (v = strchr(buf, '.')) != NULL &&
+-      *++v != '\0')
+-    dns_add_srch_internal(ctx, v);
+-
+-  return 0;
+-}
+-
+-#endif /* dns_init_internal() for !WIN32 */
+-
+-int dns_init(int do_open) {
+-  struct dns_ctx *ctx = &dns_defctx;
+-  assert(!CTXINITED(ctx));
+-  memset(ctx, 0, sizeof(*ctx));
+-  ctx->dnsc_timeout = 4;
+-  ctx->dnsc_ntries = 3;
+-  ctx->dnsc_ndots = 1;
+-  ctx->dnsc_udpbuf = DNS_EDNS0PACKET;
+-  ctx->dnsc_port = DNS_PORT;
+-  ctx->dnsc_udpsock = -1;
+-  qlist_init(&ctx->dnsc_qactive);
+-  if (dns_init_internal(ctx) != 0)
+-    return -1;
+-  dns_firstid(ctx);
+-  ctx->dnsc_flags |= DNS_INITED;
+-  return do_open ? dns_open(ctx) : 0;
+-}
+-
+-struct dns_ctx *dns_new(const struct dns_ctx *ctx) {
+-  struct dns_ctx *n;
+-  SETCTXINITED(ctx);
+-  dns_assert_ctx(ctx);
+-  n = malloc(sizeof(*n));
+-  if (!n)
+-    return NULL;
+-  *n = *ctx;
+-  n->dnsc_udpsock = -1;
+-  qlist_init(&n->dnsc_qactive);
+-  n->dnsc_nactive = 0;
+-  n->dnsc_pbuf = NULL;
+-  n->dnsc_qstatus = 0;
+-  n->dnsc_utmfn = NULL;
+-  n->dnsc_utmctx = NULL;
+-  dns_firstid(n);
+-  return n;
+-}
+-
+-void dns_free(struct dns_ctx *ctx) {
+-  struct dns_query *q;
+-  SETCTXINITED(ctx);
+-  dns_assert_ctx(ctx);
+-  dns_drop_utm(ctx);
+-  if (ctx->dnsc_udpsock >= 0)
+-    closesocket(ctx->dnsc_udpsock);
+-  if (ctx->dnsc_pbuf)
+-    free(ctx->dnsc_pbuf);
+-  while((q = qlist_pop(&ctx->dnsc_qactive)))
+-    free(q);
+-  if (ctx != &dns_defctx)
+-    free(ctx);
+-  else
+-    memset(ctx, 0, sizeof(*ctx));
+-}
+-
+-int dns_open(struct dns_ctx *ctx) {
+-  int sock;
+-  unsigned i;
+-  int port;
+-  union sockaddr_ns *sns;
+-#if HAVE_INET6
+-  unsigned have_inet6 = 0;
+-#endif
+-
+-  SETCTXINITED(ctx);
+-  assert(!CTXOPEN(ctx));
+-
+-  port = htons(ctx->dnsc_port);
+-  /* ensure we have at least one server */
+-  if (!ctx->dnsc_nserv) {
+-    sns = ctx->dnsc_serv;
+-    sns->sin.sin_family = AF_INET;
+-    sns->sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+-    ctx->dnsc_nserv = 1;
+-  }
+-
+-  for (i = 0; i < ctx->dnsc_nserv; ++i) {
+-    sns = &ctx->dnsc_serv[i];
+-    /* set port for each sockaddr */
+-#if HAVE_INET6
+-    if (sns->sa.sa_family == AF_INET6) {
+-      if (!sns->sin6.sin6_port) sns->sin6.sin6_port = port;
+-      ++have_inet6;
+-    }
+-    else
+-#endif
+-    {
+-      assert(sns->sa.sa_family == AF_INET);
+-      if (!sns->sin.sin_port) sns->sin.sin_port = port;
+-    }
+-  }
+-
+-#if !HAVE_INET6
+-  ctx->dnsc_salen = sizeof(struct sockaddr_in);
+-#else
+-  if (have_inet6 && have_inet6 < ctx->dnsc_nserv) {
+-    /* convert all IPv4 addresses to IPv6 V4MAPPED */
+-    struct sockaddr_in6 sin6;
+-    memset(&sin6, 0, sizeof(sin6));
+-    sin6.sin6_family = AF_INET6;
+-    /* V4MAPPED: ::ffff:1.2.3.4 */
+-    sin6.sin6_addr.s6_addr[10] = 0xff;
+-    sin6.sin6_addr.s6_addr[11] = 0xff;
+-    for(i = 0; i < ctx->dnsc_nserv; ++i) {
+-      sns = &ctx->dnsc_serv[i];
+-      if (sns->sa.sa_family == AF_INET) {
+-        sin6.sin6_port = sns->sin.sin_port;
+-        ((struct in_addr*)&sin6.sin6_addr)[3] = sns->sin.sin_addr;
+-        sns->sin6 = sin6;
+-      }
+-    }
+-  }
+-
+-  ctx->dnsc_salen = have_inet6 ?
+-    sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
+-
+-  if (have_inet6)
+-    sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+-  else
+-#endif /* HAVE_INET6 */
+-    sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+-
+-  if (sock < 0) {
+-    ctx->dnsc_qstatus = DNS_E_TEMPFAIL;
+-    return -1;
+-  }
+-#ifdef WIN32
+-  { unsigned long on = 1;
+-    if (ioctlsocket(sock, FIONBIO, &on) == SOCKET_ERROR) {
+-      closesocket(sock);
+-      ctx->dnsc_qstatus = DNS_E_TEMPFAIL;
+-      return -1;
+-    }
+-  }
+-#else	/* !WIN32 */
+-  if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK) < 0 ||
+-      fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) {
+-    closesocket(sock);
+-    ctx->dnsc_qstatus = DNS_E_TEMPFAIL;
+-    return -1;
+-  }
+-#endif	/* WIN32 */
+-  /* allocate the packet buffer */
+-  if (!(ctx->dnsc_pbuf = malloc(ctx->dnsc_udpbuf))) {
+-    closesocket(sock);
+-    ctx->dnsc_qstatus = DNS_E_NOMEM;
+-    errno = ENOMEM;
+-    return -1;
+-  }
+-
+-  ctx->dnsc_udpsock = sock;
+-  return sock;
+-}
+-
+-void dns_close(struct dns_ctx *ctx) {
+-  SETCTXINITED(ctx);
+-  if (ctx->dnsc_udpsock < 0) return;
+-  closesocket(ctx->dnsc_udpsock);
+-  ctx->dnsc_udpsock = -1;
+-  free(ctx->dnsc_pbuf);
+-  ctx->dnsc_pbuf = NULL;
+-}
+-
+-int dns_sock(const struct dns_ctx *ctx) {
+-  SETCTXINITED(ctx);
+-  return ctx->dnsc_udpsock;
+-}
+-
+-int dns_active(const struct dns_ctx *ctx) {
+-  SETCTXINITED(ctx);
+-  dns_assert_ctx(ctx);
+-  return ctx->dnsc_nactive;
+-}
+-
+-int dns_status(const struct dns_ctx *ctx) {
+-  SETCTX(ctx);
+-  return ctx->dnsc_qstatus;
+-}
+-void dns_setstatus(struct dns_ctx *ctx, int status) {
+-  SETCTX(ctx);
+-  ctx->dnsc_qstatus = status;
+-}
+-
+-/* End the query and return the result to the caller.
+- */
+-static void
+-dns_end_query(struct dns_ctx *ctx, struct dns_query *q,
+-              int status, void *result) {
+-  dns_query_fn *cbck = q->dnsq_cbck;
+-  void *cbdata = q->dnsq_cbdata;
+-  ctx->dnsc_qstatus = status;
+-  assert((status < 0 && result == 0) || (status >= 0 && result != 0));
+-  assert(cbck != 0);	/*XXX callback may be NULL */
+-  assert(ctx->dnsc_nactive > 0);
+-  --ctx->dnsc_nactive;
+-  /* force the query to be unconnected */
+-  /*memset(q, 0, sizeof(*q));*/
+-#ifndef NDEBUG
+-  q->dnsq_ctx = NULL;
+-#endif
+-  free(q);
+-  cbck(ctx, result, cbdata);
+-}
+-
+-#define DNS_DBG(ctx, code, sa, slen, pkt, plen) \
+-  do { \
+-    if (ctx->dnsc_udbgfn) \
+-      ctx->dnsc_udbgfn(code, (sa), slen, pkt, plen, 0, 0); \
+-  } while(0)
+-#define DNS_DBGQ(ctx, q, code, sa, slen, pkt, plen) \
+-  do { \
+-    if (ctx->dnsc_udbgfn) \
+-      ctx->dnsc_udbgfn(code, (sa), slen, pkt, plen, q, q->dnsq_cbdata); \
+-  } while(0)
+-
+-/* Try next search, filling in qDN in query.
+- * Return new qDN len or 0 if no more to search.
+- * Caller should fill up the rest of the query.
+- */
+-static unsigned dns_next_srch(const struct dns_ctx *ctx, struct dns_query *q) {
+-  unsigned ol = q->dnsq_origdnl - 1;	/* origdnl is at least 1 */
+-  dnsc_t *p = dns_payload(q->dnsq_buf) + ol;
+-  dnscc_t *dn;
+-  int n;
+-  while (q->dnsq_srchi < ctx->dnsc_nsrch) {
+-    dn = ctx->dnsc_srch[q->dnsq_srchi++];
+-    if (!*dn) {			/* root dn */
+-      if (!(q->dnsq_flags & DNS_ASIS_DONE))
+-        break;
+-    }
+-    else if ((n = dns_dntodn(dn, p, DNS_MAXDN - ol)) > 0)
+-      return n + ol;
+-  }
+-  if (q->dnsq_flags & DNS_ASIS_DONE)
+-    return 0;
+-  q->dnsq_flags |= DNS_ASIS_DONE;
+-  *p = '\0';
+-  return ol + 1;
+-}
+-
+-/* find the next server which isn't skipped starting from current.
+- * return 0 if ok, >0 if ok but we started next cycle, or <0 if
+- * number of tries exceeded or no more servers.
+- */
+-static int dns_find_serv(const struct dns_ctx *ctx, struct dns_query *q) {
+-  int cycle;
+-  if (q->dnsq_try < ctx->dnsc_ntries) for(cycle = 0;;) {
+-    if (q->dnsq_servi < ctx->dnsc_nserv) {
+-      if (!(q->dnsq_servskip & (1 << q->dnsq_servi)))
+-        return cycle;
+-      ++q->dnsq_servi;
+-    }
+-    else if (cycle || ++q->dnsq_try >= ctx->dnsc_ntries)
+-      break;
+-    else {
+-      cycle = 1;
+-      q->dnsq_servi = 0;
+-    }
+-  }
+-  return -1;
+-}
+-
+-/* send the query out and add it to the active list. */
+-static void dns_send(struct dns_ctx *ctx, struct dns_query *q, time_t now) {
+-  int n;
+-  struct dns_query *p;
+-
+-  /* if we can't send the query, return TEMPFAIL even when searching:
+-   * we can't be sure whenever the name we tried to search exists or not,
+-   * so don't continue searching, or we may find the wrong name. */
+-
+-  /* if there's no more servers, fail the query */
+-  n = dns_find_serv(ctx, q);
+-  if (n < 0) {
+-    dns_end_query(ctx, q, DNS_E_TEMPFAIL, 0);
+-    return;
+-  }
+-
+-  /* send the query */
+-  n = 10;
+-  while (sendto(ctx->dnsc_udpsock, q->dnsq_buf, q->dnsq_len, 0,
+-                &ctx->dnsc_serv[q->dnsq_servi].sa, ctx->dnsc_salen) < 0) {
+-    /*XXX just ignore the sendto() error for now and try again.
+-     * In the future, it may be possible to retrieve the error code
+-     * and find which operation/query failed.
+-     *XXX try the next server too?
+-     */
+-    if (--n) continue;
+-    /* if we can't send the query, fail it. */
+-    dns_end_query(ctx, q, DNS_E_TEMPFAIL, 0);
+-    return;
+-  }
+-  DNS_DBGQ(ctx, q, 1,
+-           &ctx->dnsc_serv[q->dnsq_servi].sa, sizeof(union sockaddr_ns),
+-           q->dnsq_buf, q->dnsq_len);
+-  q->dnsq_servwait |= 1 << q->dnsq_servi;	/* expect reply from this ns */
+-
+-  /* advance to the next server, and choose a timeout.
+-   * we will try next server in 1 secound, but start next
+-   * cycle waiting for proper timeout. */
+-  ++q->dnsq_servi;
+-  n = dns_find_serv(ctx, q) ? ctx->dnsc_timeout << (q->dnsq_try - 1) : 1;
+-
+-  q->dnsq_deadline = now = now + n;
+-
+-  /* insert the query to the tail of the list */
+-  QLIST_FOR_EACH(&ctx->dnsc_qactive, p, prev)
+-    if (p->dnsq_deadline <= now)
+-      break;
+-  qlist_insert_after(q, p);
+-
+-}
+-
+-static void dns_dummy_cb(struct dns_ctx *ctx, void *result, void *data) {
+-  if (result) free(result);
+-  data = ctx = 0;	/* used */
+-}
+-
+-struct dns_query *
+-dns_submit_dn(struct dns_ctx *ctx,
+-              dnscc_t *dn, int qcls, int qtyp, int flags,
+-              dns_parse_fn *parse, dns_query_fn *cbck, void *data) {
+-  dnsc_t *p;
+-  unsigned dnl;
+-  struct dns_query *q;
+-  SETCTXOPEN(ctx);
+-  dns_assert_ctx(ctx);
+-
+-  q = calloc(sizeof(*q), 1);
+-  if (!q) {
+-    ctx->dnsc_qstatus = DNS_E_NOMEM;
+-    return NULL;
+-  }
+-
+-#ifndef NDEBUG
+-  q->dnsq_ctx = ctx;
+-#endif
+-  q->dnsq_parse = parse;
+-  q->dnsq_cbck = cbck ? cbck : dns_dummy_cb;
+-  q->dnsq_cbdata = data;
+-
+-  flags = (flags | ctx->dnsc_flags) & ~DNS_INTERNAL;
+-  if (!ctx->dnsc_nsrch) q->dnsq_flags |= DNS_NOSRCH;
+-  if (!(flags & DNS_NORD)) q->dnsq_buf[DNS_H_F1] |= DNS_HF1_RD;
+-  if (flags & DNS_AAONLY) q->dnsq_buf[DNS_H_F1] |= DNS_HF1_AA;
+-  q->dnsq_buf[DNS_H_QDCNT2] = 1;
+-  dns_put16(q->dnsq_buf + DNS_H_QID, ctx->dnsc_nextid++);
+-
+-  q->dnsq_origdnl = dns_dnlen(dn);
+-  assert(q->dnsq_origdnl > 0 && q->dnsq_origdnl <= DNS_MAXDN);
+-  memcpy(dns_payload(q->dnsq_buf), dn, q->dnsq_origdnl);
+-  p = dns_payload(q->dnsq_buf) + q->dnsq_origdnl;
+-  if (flags & DNS_NOSRCH || dns_dnlabels(dn) > ctx->dnsc_ndots)
+-    flags |= DNS_ASIS_DONE;
+-  else if ((dnl = dns_next_srch(ctx, q)) > 0)
+-    p = dns_payload(q->dnsq_buf) + dnl;
+-  else
+-    p[-1] = '\0';
+-  q->dnsq_flags = flags;
+-  q->dnsq_typ = qtyp;
+-  p = dns_put16(p, qtyp);
+-  q->dnsq_cls = qcls;
+-  p = dns_put16(p, qcls);
+-  if (ctx->dnsc_udpbuf > DNS_MAXPACKET) {
+-    p++;			/* empty (root) DN */
+-    p = dns_put16(p, DNS_T_OPT);
+-    p = dns_put16(p, ctx->dnsc_udpbuf);
+-    p += 2;		/* EDNS0 RCODE & VERSION */
+-    p += 2;		/* rest of the TTL field */
+-    p += 2;		/* RDLEN */
+-    q->dnsq_buf[DNS_H_ARCNT2] = 1;
+-  }
+-  assert(p <= q->dnsq_buf + DNS_QBUF);
+-  q->dnsq_len = p - q->dnsq_buf;
+-
+-  qlist_add_head(q, &ctx->dnsc_qactive);
+-  ++ctx->dnsc_nactive;
+-  dns_request_utm(ctx, 0);
+-
+-  return q;
+-}
+-
+-struct dns_query *
+-dns_submit_p(struct dns_ctx *ctx,
+-             const char *name, int qcls, int qtyp, int flags,
+-             dns_parse_fn *parse, dns_query_fn *cbck, void *data) {
+-  int isabs;
+-  SETCTXOPEN(ctx);
+-  if (dns_ptodn(name, 0, ctx->dnsc_pbuf, DNS_MAXDN, &isabs) <= 0) {
+-    ctx->dnsc_qstatus = DNS_E_BADQUERY;
+-    return NULL;
+-  }
+-  if (isabs)
+-    flags |= DNS_NOSRCH;
+-  return
+-    dns_submit_dn(ctx, ctx->dnsc_pbuf, qcls, qtyp, flags, parse, cbck, data);
+-}
+-
+-/* process readable fd condition.
+- * To be usable in edge-triggered environment, the routine
+- * should consume all input so it should loop over.
+- * Note it isn't really necessary to loop here, because
+- * an application may perform the loop just fine by it's own,
+- * but in this case we should return some sensitive result,
+- * to indicate when to stop calling and error conditions.
+- * Note also we may encounter all sorts of recvfrom()
+- * errors which aren't fatal, and at the same time we may
+- * loop forever if an error IS fatal.
+- * Current loop/goto looks just terrible... */
+-void dns_ioevent(struct dns_ctx *ctx, time_t now) {
+-  int r;
+-  unsigned servi, l;
+-  struct dns_query *q;
+-  dnsc_t *pbuf;
+-  dnscc_t *pend, *pcur;
+-  void *result;
+-  union sockaddr_ns sns;
+-  socklen_t slen;
+-
+-  SETCTX(ctx);
+-  if (!CTXOPEN(ctx))
+-    return;
+-  dns_assert_ctx(ctx);
+-  pbuf = ctx->dnsc_pbuf;
+-
+-  if (!now) now = time(NULL);
+-
+-again:
+-
+-  for(;;) { /* receive the reply */
+-    dnsc_t dn[DNS_MAXDN];
+-
+-    slen = sizeof(sns);
+-    r = recvfrom(ctx->dnsc_udpsock, pbuf, ctx->dnsc_udpbuf, 0, &sns.sa, &slen);
+-    if (r < 0) {
+-      /*XXX just ignore recvfrom() errors for now.
+-       * in the future it may be possible to determine which
+-       * query failed and requeue it.
+-       * Note there may be various error conditions, triggered
+-       * by both local problems and remote problems.  It isn't
+-       * quite trivial to determine whenever an error is local
+-       * or remote.  On local errors, we should stop, while
+-       * remote errors should be ignored (for now anyway).
+-       */
+-#ifdef WIN32
+-      if (WSAGetLastError() == WSAEWOULDBLOCK)
+-#else
+-      if (errno == EAGAIN)
+-#endif
+-      {
+-        dns_request_utm(ctx, now);
+-	return;
+-      }
+-      continue;
+-    }
+-    /* ignore replies from wrong server */
+-#if HAVE_INET6
+-    if (sns.sa.sa_family == AF_INET6 && slen >= sizeof(sns.sin6)) {
+-      for (servi = 0; servi < ctx->dnsc_nserv; ++servi)
+-        if (ctx->dnsc_serv[servi].sin6.sin6_port == sns.sin6.sin6_port &&
+-            memcmp(&ctx->dnsc_serv[servi].sin6.sin6_addr,
+-                   &sns.sin6.sin6_addr, sizeof(sns.sin6.sin6_addr)) == 0)
+-          break;
+-    }
+-    else
+-#endif
+-    if (sns.sa.sa_family == AF_INET && slen >= sizeof(sns.sin)) {
+-      for (servi = 0; servi < ctx->dnsc_nserv; ++servi)
+-        if (ctx->dnsc_serv[servi].sin.sin_addr.s_addr == sns.sin.sin_addr.s_addr &&
+-            ctx->dnsc_serv[servi].sin.sin_port == sns.sin.sin_port)
+-          break;
+-    }
+-    else {
+-      DNS_DBG(ctx, -1, &sns.sa, slen, pbuf, r);
+-      continue;
+-    }
+-    if (servi >= ctx->dnsc_nserv) {
+-      DNS_DBG(ctx, -2, &sns.sa, slen, pbuf, r);
+-      continue;
+-    }
+-
+-    pend = pbuf + r;
+-    pcur = dns_payload(pbuf);
+-    if (pcur >= pend || dns_numqd(pbuf) != 1 || dns_opcode(pbuf) != 0 ||
+-        dns_getdn(pbuf, &pcur, pend, dn, sizeof(dn)) < 0 ||
+-        pcur + 4 > pend) {
+-      /*XXX ignore non-query replies and replies with numqd!=1? */
+-      DNS_DBG(ctx, -3, &sns.sa, slen, pbuf, r);
+-      continue;
+-    }
+-
+-    /* truncation bit (TC).  Ooh, we don't handle TCP (yet?),
+-     * but we do handle larger UDP sizes.
+-     * Note that e.g. djbdns will only send header if resp.
+-     * does not fit, not whatever is fit in 512 bytes. */
+-    if (dns_tc(pbuf)) {
+-      DNS_DBG(ctx, -4, &sns.sa, slen, pbuf, r);
+-      continue;	/* just ignore response for now.. any hope? */
+-    }
+-
+-    /* find the request for this reply in active queue
+-     * Note we pick any request, even queued for another
+-     * server - in case first server replies a bit later
+-     * than we expected. */
+-    for (q = QLIST_FIRST(&ctx->dnsc_qactive, next);; q = QLIST_NEXT(q, next)) {
+-      if (QLIST_ISLAST(&ctx->dnsc_qactive, q)) {
+-        /* no more requests: old reply? */
+-        DNS_DBG(ctx, -5, &sns.sa, slen, pbuf, r);
+-        goto again;
+-      }
+-      /* ignore replies that has not been sent to this server.
+-       * Note dnsq_servi is the *next* server to try. */
+-      if (!q->dnsq_try && q->dnsq_servi <= servi)
+-        continue;
+-      /*XXX ignore replies from servers we're ignoring? o/
+-      if (q->dnsq_servskip & (1 << servi))
+-        continue; */
+-      /* check qID */
+-      if (q->dnsq_buf[DNS_H_QID1] != pbuf[DNS_H_QID1] ||
+-          q->dnsq_buf[DNS_H_QID2] != pbuf[DNS_H_QID2])
+-        continue;
+-      /* check qDN, qCLS and qTYP */
+-      if (!(l = dns_dnequal(dn, dns_payload(q->dnsq_buf))) ||
+-          memcmp(pcur, dns_payload(q->dnsq_buf) + l, 4) != 0)
+-        continue;
+-      /* ok, this is expected reply with matching query. */
+-      break;
+-    }
+-
+-    break;
+-
+-  }
+-
+-  DNS_DBGQ(ctx, q, 0, &sns.sa, slen, pbuf, r);
+-
+-  /* we got a reply for our query */
+-  q->dnsq_servwait &= ~(1 << servi);	/* don't expect reply from this serv */
+-
+-  /* process the RCODE */
+-  switch(dns_rcode(pbuf)) {
+-
+-  case DNS_R_NOERROR:
+-    qlist_remove(q);
+-    if (!dns_numan(pbuf)) {	/* no data of requested type */
+-      q->dnsq_flags |= DNS_SEEN_NODATA;
+-      r = DNS_E_NODATA;
+-      break;
+-    }
+-    /* the only case where we may succeed */
+-    if (q->dnsq_parse) {
+-      r = q->dnsq_parse(dns_payload(q->dnsq_buf), pbuf, pcur, pend, &result);
+-      if (r < 0)
+-        result = NULL;
+-    }
+-    else if ((result = malloc(r)) != NULL)
+-      memcpy(result, pbuf, r);
+-    else
+-      r = DNS_E_NOMEM;
+-    /* (maybe) successeful answer (modulo nomem and parsing probs) */
+-    /* note we pass DNS_E_NODATA here */
+-    dns_end_query(ctx, q, r, result);
+-    goto again;
+-
+-  case DNS_R_NXDOMAIN:
+-    qlist_remove(q);
+-    r = DNS_E_NXDOMAIN;
+-    break;
+-
+-  case DNS_R_SERVFAIL:
+-    q->dnsq_flags |= DNS_SEEN_FAIL;
+-  case DNS_R_NOTIMPL:
+-  case DNS_R_REFUSED:
+-    /* for these rcodes, advance this request
+-     * to the next server and reschedule */
+-  default: /* unknown rcode? hmmm... */
+-    /* try next server */
+-    q->dnsq_servskip |= 1 << servi;	/* don't retry this server */
+-    if (!q->dnsq_servwait) {
+-      qlist_remove(q);
+-      dns_send(ctx, q, now);
+-    }
+-    else {
+-      /* else this is the only place where q will be left unconnected
+-       * if we will move qlist_remove() before the switch{}. */
+-    }
+-    goto again;
+-
+-  }
+-
+-  /* here we have either NODATA or NXDOMAIN */
+-  if (!(q->dnsq_flags & DNS_NOSRCH)) {
+-    /* try next element from search list */
+-    unsigned sl;
+-
+-    l = dns_dnlen(dns_payload(q->dnsq_buf)) + DNS_HSIZE;	/* past qDN */
+-    /* save qcls, qtyp and EDNS0 stuff (of len sl) in pbuf */
+-    sl = q->dnsq_len - l;
+-    memcpy(pbuf, q->dnsq_buf + l, sl);
+-    /* try next search list */
+-    l = dns_next_srch(ctx, q);
+-    if (l) {	/* something else to try, of len l */
+-      l += DNS_HSIZE;
+-      memcpy(q->dnsq_buf + l, pbuf, sl);
+-      q->dnsq_len = l + sl;
+-      q->dnsq_try = 0; q->dnsq_servi = 0;
+-      q->dnsq_servwait = q->dnsq_servskip = 0;
+-      dns_send(ctx, q, now);
+-      goto again;
+-    }
+-    /* else we have nothing more to search, end the query. */
+-    if (q->dnsq_flags & DNS_SEEN_FAIL)
+-      /* at least one server/query failed, fail the query */
+-      r = DNS_E_TEMPFAIL;
+-    else if (q->dnsq_flags & DNS_SEEN_NODATA)
+-      /* for one domain we have seen NODATA, return it */
+-      r = DNS_E_NODATA;
+-    else /* else all should be NXDOMAINs */
+-      r = DNS_E_NXDOMAIN;
+-  }
+-
+-  dns_end_query(ctx, q, r, 0);
+-  goto again;
+-}
+-
+-/* handle all timeouts */
+-int dns_timeouts(struct dns_ctx *ctx, int maxwait, time_t now) {
+-  struct dns_query *q;
+-  int w;
+-  SETCTX(ctx);
+-  dns_assert_ctx(ctx);
+-  if (!now) now = time(NULL);
+-  while((q = qlist_first(&ctx->dnsc_qactive)) && q->dnsq_deadline <= now) {
+-    qlist_remove(q);
+-    dns_send(ctx, q, now);
+-  }
+-  dns_request_utm(ctx, now);
+-  if (!q)
+-    return maxwait;
+-  w = q->dnsq_deadline - now;
+-  return maxwait < 0 || maxwait > w ? w : maxwait;
+-}
+-
+-struct dns_resolve_data {
+-  int   dnsrd_done;
+-  void *dnsrd_result;
+-};
+-
+-static void dns_resolve_cb(struct dns_ctx *ctx, void *result, void *data) {
+-  struct dns_resolve_data *d = data;
+-  d->dnsrd_result = result;
+-  d->dnsrd_done = 1;
+-  ctx = ctx;
+-}
+-
+-void *dns_resolve(struct dns_ctx *ctx, struct dns_query *q) {
+-  time_t now;
+-#ifdef HAVE_POLL
+-  struct pollfd pfd;
+-#else
+-  fd_set rfd;
+-  struct timeval tv;
+-#endif
+-  struct dns_resolve_data d;
+-  int n;
+-  SETCTXOPEN(ctx);
+-
+-  if (!q)
+-    return NULL;
+-
+-  assert(ctx == q->dnsq_ctx);
+-  dns_assert_ctx(ctx);
+-  /* do not allow re-resolving syncronous queries */
+-  assert(q->dnsq_cbck != dns_resolve_cb && "can't resolve syncronous query");
+-  if (q->dnsq_cbck == dns_resolve_cb) {
+-    ctx->dnsc_qstatus = DNS_E_BADQUERY;
+-    return NULL;
+-  }
+-  q->dnsq_cbck = dns_resolve_cb;
+-  q->dnsq_cbdata = &d;
+-  d.dnsrd_done = 0;
+-
+-#ifdef HAVE_POLL
+-  pfd.fd = ctx->dnsc_udpsock;
+-  pfd.events = POLLIN;
+-#else
+-  FD_ZERO(&rfd);
+-#endif
+-
+-  now = time(NULL);
+-  while(!d.dnsrd_done && (n = dns_timeouts(ctx, -1, now)) >= 0) {
+-#ifdef HAVE_POLL
+-    n = poll(&pfd, 1, n * 1000);
+-#else
+-    tv.tv_sec = n;
+-    tv.tv_usec = 0;
+-    FD_SET(ctx->dnsc_udpsock, &rfd);
+-    n = select(ctx->dnsc_udpsock + 1, &rfd, NULL, NULL, &tv);
+-#endif
+-    now = time(NULL);
+-    if (n > 0)
+-      dns_ioevent(ctx, now);
+-  }
+-
+-  return d.dnsrd_result;
+-}
+-
+-void *dns_resolve_dn(struct dns_ctx *ctx,
+-                     dnscc_t *dn, int qcls, int qtyp, int flags,
+-                     dns_parse_fn *parse) {
+-  return
+-    dns_resolve(ctx,
+-      dns_submit_dn(ctx, dn, qcls, qtyp, flags, parse, NULL, NULL));
+-}
+-
+-void *dns_resolve_p(struct dns_ctx *ctx,
+-                    const char *name, int qcls, int qtyp, int flags,
+-                    dns_parse_fn *parse) {
+-  return
+-    dns_resolve(ctx,
+-      dns_submit_p(ctx, name, qcls, qtyp, flags, parse, NULL, NULL));
+-}
+-
+-int dns_cancel(struct dns_ctx *ctx, struct dns_query *q) {
+-  SETCTX(ctx);
+-  dns_assert_ctx(ctx);
+-  assert(q->dnsq_ctx == ctx);
+-  /* do not allow cancelling syncronous queries */
+-  assert(q->dnsq_cbck != dns_resolve_cb && "can't cancel syncronous query");
+-  if (q->dnsq_cbck == dns_resolve_cb)
+-    return (ctx->dnsc_qstatus = DNS_E_BADQUERY);
+-  qlist_remove(q);
+-  --ctx->dnsc_nactive;
+-  dns_request_utm(ctx, 0);
+-  return 0;
+-}
+-
+diff --git a/udns/source/udns_rr_a.c b/udns/source/udns_rr_a.c
+deleted file mode 100644
+index 2266252..0000000
+--- a/udns/source/udns_rr_a.c
++++ /dev/null
+@@ -1,124 +0,0 @@
+-/* $Id: udns_rr_a.c,v 1.14 2005/04/20 06:44:34 mjt Exp $
+-   parse/query A/AAAA IN records
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#include <string.h>
+-#include <stdlib.h>
+-#include <assert.h>
+-#ifdef WIN32
+-# include <winsock2.h>          /* includes <windows.h> */
+-# include <ws2tcpip.h>          /* needed for struct in6_addr */
+-#else
+-# include <sys/types.h>
+-# include <netinet/in.h>
+-#endif
+-#include "udns.h"
+-
+-/* here, we use common routine to parse both IPv4 and IPv6 addresses.
+- */
+-
+-/* this structure should match dns_rr_a[46] */
+-struct dns_rr_a {
+-  dns_rr_common(dnsa);
+-  unsigned char *dnsa_addr;
+-};
+-
+-static int
+-dns_parse_a(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
+-            void **result, unsigned dsize) {
+-  struct dns_rr_a *ret;
+-  struct dns_parse p;
+-  struct dns_rr rr;
+-  int r;
+-
+-  /* first, validate and count number of addresses */
+-  dns_initparse(&p, qdn, pkt, cur, end);
+-  while((r = dns_nextrr(&p, &rr)) > 0)
+-    if (rr.dnsrr_dsz != dsize)
+-      return DNS_E_PROTOCOL;
+-  if (r < 0)
+-    return DNS_E_PROTOCOL;
+-  else if (!p.dnsp_nrr)
+-    return DNS_E_NODATA;
+-
+-  ret = malloc(sizeof(*ret) + dsize * p.dnsp_nrr + dns_stdrr_size(&p));
+-  if (!ret)
+-    return DNS_E_NOMEM;
+-
+-  ret->dnsa_nrr = p.dnsp_nrr;
+-  ret->dnsa_addr = (unsigned char*)(ret+1);
+-
+-  /* copy the RRs */
+-  for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r)
+-    memcpy(ret->dnsa_addr + dsize * r, rr.dnsrr_dptr, dsize);
+-
+-  dns_stdrr_finish((struct dns_rr_null *)ret,
+-                   (char *)(ret->dnsa_addr + dsize * p.dnsp_nrr), &p);
+-  *result = ret;
+-  return 0;
+-}
+-
+-int
+-dns_parse_a4(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
+-             void **result) {
+-  assert(sizeof(struct in_addr) == 4);
+-  assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_A);
+-  return dns_parse_a(qdn, pkt, cur, end, result, 4);
+-}
+-
+-struct dns_query *
+-dns_submit_a4(struct dns_ctx *ctx, const char *name, int flags,
+-              dns_query_a4_fn *cbck, void *data) {
+-  return
+-    dns_submit_p(ctx, name, DNS_C_IN, DNS_T_A, flags,
+-                 dns_parse_a4, (dns_query_fn*)cbck, data);
+-}
+-
+-struct dns_rr_a4 *
+-dns_resolve_a4(struct dns_ctx *ctx, const char *name, int flags) {
+-  return (struct dns_rr_a4 *)
+-    dns_resolve_p(ctx, name, DNS_C_IN, DNS_T_A, flags, dns_parse_a4);
+-}
+-
+-int
+-dns_parse_a6(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
+-             void **result) {
+-#ifdef AF_INET6
+-  assert(sizeof(struct in6_addr) == 16);
+-#endif
+-  assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_AAAA);
+-  return dns_parse_a(qdn, pkt, cur, end, result, 16);
+-}
+-
+-struct dns_query *
+-dns_submit_a6(struct dns_ctx *ctx, const char *name, int flags,
+-              dns_query_a6_fn *cbck, void *data) {
+-  return
+-    dns_submit_p(ctx, name, DNS_C_IN, DNS_T_AAAA, flags,
+-                 dns_parse_a6, (dns_query_fn*)cbck, data);
+-}
+-
+-struct dns_rr_a6 *
+-dns_resolve_a6(struct dns_ctx *ctx, const char *name, int flags) {
+-  return (struct dns_rr_a6 *)
+-    dns_resolve_p(ctx, name, DNS_C_IN, DNS_T_AAAA, flags, dns_parse_a6);
+-}
+diff --git a/udns/source/udns_rr_mx.c b/udns/source/udns_rr_mx.c
+deleted file mode 100644
+index cf83483..0000000
+--- a/udns/source/udns_rr_mx.c
++++ /dev/null
+@@ -1,91 +0,0 @@
+-/* $Id: udns_rr_mx.c,v 1.13 2005/04/20 06:44:34 mjt Exp $
+-   parse/query MX IN records
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#include <string.h>
+-#include <stdlib.h>
+-#include <assert.h>
+-#include "udns.h"
+-
+-int
+-dns_parse_mx(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
+-             void **result) {
+-  struct dns_rr_mx *ret;
+-  struct dns_parse p;
+-  struct dns_rr rr;
+-  int r, l;
+-  char *sp;
+-  dnsc_t mx[DNS_MAXDN];
+-
+-  assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_MX);
+-
+-  /* first, validate the answer and count size of the result */
+-  l = 0;
+-  dns_initparse(&p, qdn, pkt, cur, end);
+-  while((r = dns_nextrr(&p, &rr)) > 0) {
+-    cur = rr.dnsrr_dptr + 2;
+-    r = dns_getdn(pkt, &cur, end, mx, sizeof(mx));
+-    if (r <= 0 || cur != rr.dnsrr_dend)
+-      return DNS_E_PROTOCOL;
+-    l += dns_dntop_size(mx);
+-  }
+-  if (r < 0)
+-    return DNS_E_PROTOCOL;
+-  if (!p.dnsp_nrr)
+-    return DNS_E_NODATA;
+-
+-  /* next, allocate and set up result */
+-  l += dns_stdrr_size(&p);
+-  ret = malloc(sizeof(*ret) + sizeof(struct dns_mx) * p.dnsp_nrr + l);
+-  if (!ret)
+-    return DNS_E_NOMEM;
+-  ret->dnsmx_nrr = p.dnsp_nrr;
+-  ret->dnsmx_mx = (struct dns_mx *)(ret+1);
+-
+-  /* and 3rd, fill in result, finally */
+-  sp = (char*)(ret->dnsmx_mx + p.dnsp_nrr);
+-  for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r) {
+-    ret->dnsmx_mx[r].name = sp;
+-    cur = rr.dnsrr_dptr;
+-    ret->dnsmx_mx[r].priority = dns_get16(cur);
+-    cur += 2;
+-    dns_getdn(pkt, &cur, end, mx, sizeof(mx));
+-    sp += dns_dntop(mx, sp, DNS_MAXNAME);
+-  }
+-  dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p);
+-  *result = ret;
+-  return 0;
+-}
+-
+-struct dns_query *
+-dns_submit_mx(struct dns_ctx *ctx, const char *name, int flags,
+-              dns_query_mx_fn *cbck, void *data) {
+-  return
+-    dns_submit_p(ctx, name, DNS_C_IN, DNS_T_MX, flags,
+-                 dns_parse_mx, (dns_query_fn *)cbck, data);
+-}
+-
+-struct dns_rr_mx *
+-dns_resolve_mx(struct dns_ctx *ctx, const char *name, int flags) {
+-  return (struct dns_rr_mx *)
+-    dns_resolve_p(ctx, name, DNS_C_IN, DNS_T_MX, flags, dns_parse_mx);
+-}
+diff --git a/udns/source/udns_rr_naptr.c b/udns/source/udns_rr_naptr.c
+deleted file mode 100644
+index ec4f514..0000000
+--- a/udns/source/udns_rr_naptr.c
++++ /dev/null
+@@ -1,128 +0,0 @@
+-/* $Id: udns_rr_naptr.c,v 1.1 2006/11/28 22:58:04 mjt Exp $
+-   parse/query NAPTR IN records
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   Copyright (C) 2006  Mikael Magnusson <mikma at users.sourceforge.net>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#include <string.h>
+-#include <stdlib.h>
+-#include <assert.h>
+-#include "udns.h"
+-
+-/* Get a single string for NAPTR record, pretty much like a DN label.
+- * String length is in first byte in *cur, so it can't be >255.
+- */
+-static int dns_getstr(dnscc_t **cur, dnscc_t *ep, char *buf)
+-{
+-  unsigned l;
+-  dnscc_t *cp = *cur;
+-
+-  l = *cp++;
+-  if (cp + l > ep)
+-    return DNS_E_PROTOCOL;
+-  if (buf) {
+-    memcpy(buf, cp, l);
+-    buf[l] = '\0';
+-  }
+-  cp += l;
+-
+-  *cur = cp;
+-  return l + 1;
+-}
+-
+-int
+-dns_parse_naptr(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
+-                void **result) {
+-  struct dns_rr_naptr *ret;
+-  struct dns_parse p;
+-  struct dns_rr rr;
+-  int r, l;
+-  char *sp;
+-  dnsc_t dn[DNS_MAXDN];
+-
+-  assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_NAPTR);
+-
+-  /* first, validate the answer and count size of the result */
+-  l = 0;
+-  dns_initparse(&p, qdn, pkt, cur, end);
+-  while((r = dns_nextrr(&p, &rr)) > 0) {
+-    int i;
+-    dnscc_t *ep = rr.dnsrr_dend;
+-
+-    /* first 4 bytes: order & preference */
+-    cur = rr.dnsrr_dptr + 4;
+-
+-    /* flags, services and regexp */
+-    for (i = 0; i < 3; i++) {
+-      r = dns_getstr(&cur, ep, NULL);
+-      if (r < 0)
+-        return r;
+-      l += r;
+-    }
+-    /* replacement */
+-    r = dns_getdn(pkt, &cur, end, dn, sizeof(dn));
+-    if (r <= 0 || cur != rr.dnsrr_dend)
+-      return DNS_E_PROTOCOL;
+-    l += dns_dntop_size(dn);
+-  }
+-  if (r < 0)
+-    return DNS_E_PROTOCOL;
+-  if (!p.dnsp_nrr)
+-    return DNS_E_NODATA;
+-
+-  /* next, allocate and set up result */
+-  l += dns_stdrr_size(&p);
+-  ret = malloc(sizeof(*ret) + sizeof(struct dns_naptr) * p.dnsp_nrr + l);
+-  if (!ret)
+-    return DNS_E_NOMEM;
+-  ret->dnsnaptr_nrr = p.dnsp_nrr;
+-  ret->dnsnaptr_naptr = (struct dns_naptr *)(ret+1);
+-
+-  /* and 3rd, fill in result, finally */
+-  sp = (char*)(&ret->dnsnaptr_naptr[p.dnsp_nrr]);
+-  for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r) {
+-    cur = rr.dnsrr_dptr;
+-    ret->dnsnaptr_naptr[r].order = dns_get16(cur); cur += 2;
+-    ret->dnsnaptr_naptr[r].preference = dns_get16(cur); cur += 2;
+-    sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].flags = sp));
+-    sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].service = sp));
+-    sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].regexp = sp));
+-    dns_getdn(pkt, &cur, end, dn, sizeof(dn));
+-    sp += dns_dntop(dn, (ret->dnsnaptr_naptr[r].replacement = sp), DNS_MAXNAME);
+-  }
+-  dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p);
+-  *result = ret;
+-  return 0;
+-}
+-
+-struct dns_query *
+-dns_submit_naptr(struct dns_ctx *ctx, const char *name, int flags,
+-                 dns_query_naptr_fn *cbck, void *data) {
+-  return
+-    dns_submit_p(ctx, name, DNS_C_IN, DNS_T_NAPTR, flags,
+-                 dns_parse_naptr, (dns_query_fn *)cbck, data);
+-}
+-
+-struct dns_rr_naptr *
+-dns_resolve_naptr(struct dns_ctx *ctx, const char *name, int flags) {
+-  return (struct dns_rr_naptr *)
+-    dns_resolve_p(ctx, name, DNS_C_IN, DNS_T_NAPTR, flags, dns_parse_naptr);
+-}
+diff --git a/udns/source/udns_rr_ptr.c b/udns/source/udns_rr_ptr.c
+deleted file mode 100644
+index 410af65..0000000
+--- a/udns/source/udns_rr_ptr.c
++++ /dev/null
+@@ -1,109 +0,0 @@
+-/* $Id: udns_rr_ptr.c,v 1.15 2005/09/12 11:21:06 mjt Exp $
+-   parse/query PTR records
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#include <stdlib.h>
+-#include <assert.h>
+-#include "udns.h"
+-
+-int
+-dns_parse_ptr(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
+-              void **result) {
+-  struct dns_rr_ptr *ret;
+-  struct dns_parse p;
+-  struct dns_rr rr;
+-  int r, l, c;
+-  char *sp;
+-  dnsc_t ptr[DNS_MAXDN];
+-
+-  assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_PTR);
+-
+-  /* first, validate the answer and count size of the result */
+-  l = c = 0;
+-  dns_initparse(&p, qdn, pkt, cur, end);
+-  while((r = dns_nextrr(&p, &rr)) > 0) {
+-    cur = rr.dnsrr_dptr;
+-    r = dns_getdn(pkt, &cur, end, ptr, sizeof(ptr));
+-    if (r <= 0 || cur != rr.dnsrr_dend)
+-      return DNS_E_PROTOCOL;
+-    l += dns_dntop_size(ptr);
+-    ++c;
+-  }
+-  if (r < 0)
+-    return DNS_E_PROTOCOL;
+-  if (!c)
+-    return DNS_E_NODATA;
+-
+-  /* next, allocate and set up result */
+-  ret = malloc(sizeof(*ret) + sizeof(char **) * c + l + dns_stdrr_size(&p));
+-  if (!ret)
+-    return DNS_E_NOMEM;
+-  ret->dnsptr_nrr = c;
+-  ret->dnsptr_ptr = (char **)(ret+1);
+-
+-  /* and 3rd, fill in result, finally */
+-  sp = (char*)(ret->dnsptr_ptr + c);
+-  c = 0;
+-  dns_rewind(&p, qdn);
+-  while((r = dns_nextrr(&p, &rr)) > 0) {
+-    ret->dnsptr_ptr[c] = sp;
+-    cur = rr.dnsrr_dptr;
+-    dns_getdn(pkt, &cur, end, ptr, sizeof(ptr));
+-    sp += dns_dntop(ptr, sp, DNS_MAXNAME);
+-    ++c;
+-  }
+-  dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p);
+-  *result = ret;
+-  return 0;
+-}
+-
+-struct dns_query *
+-dns_submit_a4ptr(struct dns_ctx *ctx, const struct in_addr *addr,
+-                 dns_query_ptr_fn *cbck, void *data) {
+-  dnsc_t dn[DNS_A4RSIZE];
+-  dns_a4todn(addr, 0, dn, sizeof(dn));
+-  return
+-    dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_PTR, DNS_NOSRCH,
+-                  dns_parse_ptr, (dns_query_fn *)cbck, data);
+-}
+-
+-struct dns_rr_ptr *
+-dns_resolve_a4ptr(struct dns_ctx *ctx, const struct in_addr *addr) {
+-  return (struct dns_rr_ptr *)
+-    dns_resolve(ctx, dns_submit_a4ptr(ctx, addr, NULL, NULL));
+-}
+-
+-struct dns_query *
+-dns_submit_a6ptr(struct dns_ctx *ctx, const struct in6_addr *addr,
+-                 dns_query_ptr_fn *cbck, void *data) {
+-  dnsc_t dn[DNS_A6RSIZE];
+-  dns_a6todn(addr, 0, dn, sizeof(dn));
+-  return
+-    dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_PTR, DNS_NOSRCH,
+-                  dns_parse_ptr, (dns_query_fn *)cbck, data);
+-}
+-
+-struct dns_rr_ptr *
+-dns_resolve_a6ptr(struct dns_ctx *ctx, const struct in6_addr *addr) {
+-  return (struct dns_rr_ptr *)
+-    dns_resolve(ctx, dns_submit_a6ptr(ctx, addr, NULL, NULL));
+-}
+diff --git a/udns/source/udns_rr_srv.c b/udns/source/udns_rr_srv.c
+deleted file mode 100644
+index 56bbbf7..0000000
+--- a/udns/source/udns_rr_srv.c
++++ /dev/null
+@@ -1,154 +0,0 @@
+-/* $Id: udns_rr_srv.c,v 1.2 2005/09/12 12:26:22 mjt Exp $
+-   parse/query SRV IN (rfc2782) records
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+-   Copyright 2005 Thadeu Lima de Souza Cascardo <cascardo at minaslivre.org>
+-
+-   2005-09-11:
+-   Changed MX parser file into a SRV parser file
+-
+- */
+-
+-#include <string.h>
+-#include <stdlib.h>
+-#include <assert.h>
+-#include "udns.h"
+-
+-int
+-dns_parse_srv(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
+-              void **result) {
+-  struct dns_rr_srv *ret;
+-  struct dns_parse p;
+-  struct dns_rr rr;
+-  int r, l;
+-  char *sp;
+-  dnsc_t srv[DNS_MAXDN];
+-
+-  assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_SRV);
+-
+-  /* first, validate the answer and count size of the result */
+-  l = 0;
+-  dns_initparse(&p, qdn, pkt, cur, end);
+-  while((r = dns_nextrr(&p, &rr)) > 0) {
+-    cur = rr.dnsrr_dptr + 6;
+-    r = dns_getdn(pkt, &cur, end, srv, sizeof(srv));
+-    if (r <= 0 || cur != rr.dnsrr_dend)
+-      return DNS_E_PROTOCOL;
+-    l += dns_dntop_size(srv);
+-  }
+-  if (r < 0)
+-    return DNS_E_PROTOCOL;
+-  if (!p.dnsp_nrr)
+-    return DNS_E_NODATA;
+-
+-  /* next, allocate and set up result */
+-  l += dns_stdrr_size(&p);
+-  ret = malloc(sizeof(*ret) + sizeof(struct dns_srv) * p.dnsp_nrr + l);
+-  if (!ret)
+-    return DNS_E_NOMEM;
+-  ret->dnssrv_nrr = p.dnsp_nrr;
+-  ret->dnssrv_srv = (struct dns_srv *)(ret+1);
+-
+-  /* and 3rd, fill in result, finally */
+-  sp = (char*)(ret->dnssrv_srv + p.dnsp_nrr);
+-  for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r) {
+-    ret->dnssrv_srv[r].name = sp;
+-    cur = rr.dnsrr_dptr;
+-    ret->dnssrv_srv[r].priority = dns_get16(cur);
+-    ret->dnssrv_srv[r].weight = dns_get16(cur+2);
+-    ret->dnssrv_srv[r].port = dns_get16(cur+4);
+-    cur += 6;
+-    dns_getdn(pkt, &cur, end, srv, sizeof(srv));
+-    sp += dns_dntop(srv, sp, DNS_MAXNAME);
+-  }
+-  dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p);
+-  *result = ret;
+-  return 0;
+-}
+-
+-/* Add a single service or proto name prepending an undescore (_),
+- * according to rfc2782 rules.
+- * Return 0 or the label length.
+- * Routing assumes dn holds enouth space for a single DN label. */
+-static unsigned add_sname(dnsc_t *dn, const char *sn) {
+-  unsigned l;
+-  l = dns_ptodn(sn, 0, dn + 1, DNS_MAXLABEL-1, NULL);
+-  if (l <= 1 || l - 2 != dn[1])
+-    /* Should we really check if sn is exactly one label?  Do we care? */
+-    return 0;
+-  dn[0] = l - 1;
+-  dn[1] = '_';
+-  return l;
+-}
+-
+-/* Construct a domain name for SRV query from the given name, service and
+- * protocol (service may be NULL in which case protocol isn't used).
+- * Return negative value on error (malformed query),
+- * or addition query flag(s) to use.
+- */
+-static int
+-build_srv_dn(dnsc_t *dn, const char *name, const char *srv, const char *proto)
+-{
+-  unsigned p = 0, l;
+-  int isabs;
+-  if (srv) {
+-    l = add_sname(dn + p, srv);
+-    if (!l)
+-      return -1;
+-    p += l;
+-    l = add_sname(dn + p, proto);
+-    if (!l)
+-      return -1;
+-    p += l;
+-  }
+-  l = dns_ptodn(name, 0, dn + p, DNS_MAXDN - p, &isabs);
+-  if (!l)
+-    return -1;
+-  return isabs ? DNS_NOSRCH : 0;
+-}
+-
+-struct dns_query *
+-dns_submit_srv(struct dns_ctx *ctx,
+-               const char *name, const char *srv, const char *proto,
+-               int flags, dns_query_srv_fn *cbck, void *data) {
+-  dnsc_t dn[DNS_MAXDN];
+-  int r = build_srv_dn(dn, name, srv, proto);
+-  if (r < 0) {
+-    dns_setstatus (ctx, DNS_E_BADQUERY);
+-    return NULL;
+-  }
+-  return
+-    dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_SRV, flags | r,
+-                  dns_parse_srv, (dns_query_fn *)cbck, data);
+-}
+-
+-struct dns_rr_srv *
+-dns_resolve_srv(struct dns_ctx *ctx,
+-                const char *name, const char *srv, const char *proto, int flags)
+-{
+-  dnsc_t dn[DNS_MAXDN];
+-  int r = build_srv_dn(dn, name, srv, proto);
+-  if (r < 0) {
+-    dns_setstatus(ctx, DNS_E_BADQUERY);
+-    return NULL;
+-  }
+-  return (struct dns_rr_srv *)
+-    dns_resolve_dn(ctx, dn, DNS_C_IN, DNS_T_SRV, flags | r, dns_parse_srv);
+-}
+diff --git a/udns/source/udns_rr_txt.c b/udns/source/udns_rr_txt.c
+deleted file mode 100644
+index ecc71f0..0000000
+--- a/udns/source/udns_rr_txt.c
++++ /dev/null
+@@ -1,98 +0,0 @@
+-/* $Id: udns_rr_txt.c,v 1.15 2006/11/28 22:45:20 mjt Exp $
+-   parse/query TXT records
+-
+-   Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
+-   This file is part of UDNS library, an async DNS stub resolver.
+-
+-   This library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   This library 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
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with this library, in file named COPYING.LGPL; if not,
+-   write to the Free Software Foundation, Inc., 59 Temple Place,
+-   Suite 330, Boston, MA  02111-1307  USA
+-
+- */
+-
+-#include <string.h>
+-#include <stdlib.h>
+-#include <assert.h>
+-#include "udns.h"
+-
+-int
+-dns_parse_txt(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
+-              void **result) {
+-  struct dns_rr_txt *ret;
+-  struct dns_parse p;
+-  struct dns_rr rr;
+-  int r, l;
+-  dnsc_t *sp;
+-  dnscc_t *cp, *ep;
+-
+-  assert(dns_get16(cur+0) == DNS_T_TXT);
+-
+-  /* first, validate the answer and count size of the result */
+-  l = 0;
+-  dns_initparse(&p, qdn, pkt, cur, end);
+-  while((r = dns_nextrr(&p, &rr)) > 0) {
+-    cp = rr.dnsrr_dptr; ep = rr.dnsrr_dend;
+-    while(cp < ep) {
+-      r = *cp++;
+-      if (cp + r > ep)
+-        return DNS_E_PROTOCOL;
+-      l += r;
+-      cp += r;
+-    }
+-  }
+-  if (r < 0)
+-    return DNS_E_PROTOCOL;
+-  if (!p.dnsp_nrr)
+-    return DNS_E_NODATA;
+-
+-  /* next, allocate and set up result */
+-  l +=  (sizeof(struct dns_txt) + 1) * p.dnsp_nrr + dns_stdrr_size(&p);
+-  ret = malloc(sizeof(*ret) + l);
+-  if (!ret)
+-    return DNS_E_NOMEM;
+-  ret->dnstxt_nrr = p.dnsp_nrr;
+-  ret->dnstxt_txt = (struct dns_txt *)(ret+1);
+-
+-  /* and 3rd, fill in result, finally */
+-  sp = (dnsc_t*)(ret->dnstxt_txt + p.dnsp_nrr);
+-  for(dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr) > 0; ++r) {
+-    ret->dnstxt_txt[r].txt = sp;
+-    cp = rr.dnsrr_dptr; ep = rr.dnsrr_dend;
+-    while(cp < ep) {
+-      l = *cp++;
+-      memcpy(sp, cp, l);
+-      sp += l;
+-      cp += l;
+-    }
+-    ret->dnstxt_txt[r].len = sp - ret->dnstxt_txt[r].txt;
+-    *sp++ = '\0';
+-  }
+-  dns_stdrr_finish((struct dns_rr_null *)ret, (char*)sp, &p);
+-  *result = ret;
+-  return 0;
+-}
+-
+-struct dns_query *
+-dns_submit_txt(struct dns_ctx *ctx, const char *name, int qcls, int flags,
+-               dns_query_txt_fn *cbck, void *data) {
+-  return
+-    dns_submit_p(ctx, name, qcls, DNS_T_TXT, flags,
+-                 dns_parse_txt, (dns_query_fn *)cbck, data);
+-}
+-
+-struct dns_rr_txt *
+-dns_resolve_txt(struct dns_ctx *ctx, const char *name, int qcls, int flags) {
+-  return (struct dns_rr_txt *)
+-    dns_resolve_p(ctx, name, qcls, DNS_T_TXT, flags, dns_parse_txt);
+-}
+-- 
+1.7.2.1
+
diff --git a/libmnetutil.spec b/libmnetutil.spec
new file mode 100644
index 0000000..7a055ca
--- /dev/null
+++ b/libmnetutil.spec
@@ -0,0 +1,79 @@
+Summary:		Minisip library providing various C++ network classes
+Name:			libmnetutil
+Version:		0.8.0
+Release:		0.2.20100629svn3775%{?dist}
+License:		LGPLv2+
+URL:			http://www.minisip.org/
+Group:			System Environment/Libraries
+# svn export -r 3775  svn://svn.minisip.org/minisip/trunk/libmnetutil libmnetutil-0.8.0
+# tar cjf libmnetutil-0.8.0.tar.bz2 libmnetutil-0.8.0/
+Source0:		%{name}-%{version}.tar.bz2
+Patch0:			libmnetutil-0001-Remove-bundled-udns.patch
+BuildRequires:		autoconf
+BuildRequires:		automake
+BuildRequires:		libtool
+BuildRequires:		libmutil-devel >= 0.8.0
+BuildRequires:		udns-devel
+BuildRoot:		%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+
+%description
+libmnetutil is a library providing convenient C++ network utilities
+(UDP/TCP/TLS sockets, IP addresses). It is used by the minisip project.
+
+%package devel
+Summary:		Development files for the libmnetutil library
+Group:			Development/Libraries
+Requires:		%{name} = %{version}-%{release}
+Requires:		automake
+Requires:		pkgconfig
+
+
+%description devel
+This package contains the development files for library %{name}.
+
+%prep
+%setup -q
+%patch0 -p1 -b .udns
+
+%build
+sh ./bootstrap
+%configure --disable-static
+make %{?_smp_mflags}
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make DESTDIR=$RPM_BUILD_ROOT install
+rm -rf $RPM_BUILD_ROOT%{_libdir}/*.la
+# Removed installed examples
+rm -rf $RPM_BUILD_ROOT%{_datadir}/%{name}
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+
+%files
+%defattr(-,root,root,-)
+%doc AUTHORS README COPYING.LIB
+%{_libdir}/*.so.*
+
+%files devel
+%defattr(-,root,root)
+%doc examples/tcpclient.cpp
+%doc examples/tcpserver.cpp
+%{_libdir}/*.so
+%{_libdir}/pkgconfig/%{name}.pc
+%{_includedir}/*
+%{_datadir}/aclocal/*.m4
+
+
+%changelog
+* Sun Sep 26 2010 Peter Lemenkov <lemenkov at gmail.com> - 0.8.0-0.2.20100629svn3775
+- Properly placed examples
+- Changed descriptions
+
+* Mon Aug 23 2010 Peter Lemenkov <lemenkov at gmail.com> - 0.8.0-0.1.20100629svn3775
+- Initial package for Fedora
diff --git a/sources b/sources
index e69de29..64e8d68 100644
--- a/sources
+++ b/sources
@@ -0,0 +1 @@
+0e0de89d8c816f7cc287816d95769230  libmnetutil-0.8.0.tar.bz2


More information about the scm-commits mailing list