Browse Source

Add DNS API.

Missing functional tests. I'm not sure how to do tests because I don't want
to rely on the fact that users have an internet connection.
v0.7.4-release
Ryan 16 years ago
parent
commit
41d89f611f
  1. 4
      LICENSE
  2. 14
      deps/udns/.cvsignore
  3. 504
      deps/udns/COPYING.LGPL
  4. 196
      deps/udns/Makefile.in
  5. 85
      deps/udns/NEWS
  6. 222
      deps/udns/NOTES
  7. 69
      deps/udns/TODO
  8. 167
      deps/udns/configure
  9. 268
      deps/udns/configure.lib
  10. 136
      deps/udns/debian/changelog
  11. 33
      deps/udns/debian/control
  12. 23
      deps/udns/debian/copyright
  13. 93
      deps/udns/debian/rules
  14. 182
      deps/udns/dnsget.1
  15. 726
      deps/udns/dnsget.c
  16. 113
      deps/udns/ex-rdns.c
  17. 165
      deps/udns/getopt.c
  18. 327
      deps/udns/inet_XtoX.c
  19. 151
      deps/udns/rblcheck.1
  20. 377
      deps/udns/rblcheck.c
  21. 1351
      deps/udns/udns.3
  22. 745
      deps/udns/udns.h
  23. 50
      deps/udns/udns_XtoX.c
  24. 160
      deps/udns/udns_bl.c
  25. 382
      deps/udns/udns_dn.c
  26. 30
      deps/udns/udns_dntosp.c
  27. 231
      deps/udns/udns_init.c
  28. 67
      deps/udns/udns_misc.c
  29. 169
      deps/udns/udns_parse.c
  30. 1294
      deps/udns/udns_resolver.c
  31. 123
      deps/udns/udns_rr_a.c
  32. 91
      deps/udns/udns_rr_mx.c
  33. 128
      deps/udns/udns_rr_naptr.c
  34. 109
      deps/udns/udns_rr_ptr.c
  35. 154
      deps/udns/udns_rr_srv.c
  36. 98
      deps/udns/udns_rr_txt.c
  37. 302
      src/dns.cc
  38. 14
      src/dns.h
  39. 33
      src/events.cc
  40. 11
      src/events.h
  41. 34
      src/file.cc
  42. 5
      src/node.cc
  43. 4
      src/object_wrap.h
  44. 26
      test/mjsunit/disabled/test_dns.js
  45. 69
      website/api.txt
  46. 83
      wscript

4
LICENSE

@ -22,6 +22,10 @@ are:
- The SCONS build system, located at tools/scons. Copyrighted by the SCONS - The SCONS build system, located at tools/scons. Copyrighted by the SCONS
Foundation. Released under an MIT license. Foundation. Released under an MIT license.
- UDNS, an asynchronous DNS client, located at deps/udns. Copyrighted by
Michael Tokarev <mjt@corpit.ru>. Released under the GNU Lesser General
Public License version 2.1.
Additionally deps/http_parser is based on Zed Shaw's Mongrel. Mongrel is Additionally deps/http_parser is based on Zed Shaw's Mongrel. Mongrel is
copyrighted by Zed Shaw and distributed under GPL2 or a permissive open copyrighted by Zed Shaw and distributed under GPL2 or a permissive open
licence. See deps/http_parser/LICENCE for more information. licence. See deps/http_parser/LICENCE for more information.

14
deps/udns/.cvsignore

@ -0,0 +1,14 @@
udns*.tar.gz
udns_codes.c
udns.3.html
*.lo
*_s
libudns.so.*
dnsget
ex-rdns
rblcheck
Makefile
config.h
config.status
config.log
build-stamp

504
deps/udns/COPYING.LGPL

@ -0,0 +1,504 @@
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!

196
deps/udns/Makefile.in

@ -0,0 +1,196 @@
#! /usr/bin/make -rf
# $Id: Makefile.in,v 1.11 2007/01/15 21:19:08 mjt Exp $
# libudns Makefile
#
# Copyright (C) 2005 Michael Tokarev <mjt@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
NAME = udns
VERS = 0.0.9
SRCS = udns_dn.c udns_dntosp.c udns_parse.c udns_resolver.c udns_init.c \
udns_misc.c udns_XtoX.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) \
NEWS TODO NOTES Makefile.in configure configure.lib \
inet_XtoX.c getopt.c
OBJS = $(SRCS:.c=.o) $(GEN:.c=.o)
LIB = lib$(NAME).a
LIBFL = -L. -l$(NAME)
SOVER = 0
SOBJS = $(OBJS:.o=.lo)
SOLIB = lib$(NAME)_s.so
SOLIBV = lib$(NAME).so.$(SOVER)
SOLIBFL= -L. -l$(NAME)_s
LIBS = $(LIB) $(SOLIBV)
UTILS = $(USRCS:.c=)
UOBJS = $(USRCS:.c=.o)
SOUTILS = $(USRCS:.c=_s)
NAMEPFX = $(NAME)-$(VERS)
CC = @CC@
CFLAGS = @CFLAGS@
CDEFS = @CDEFS@
PICFLAGS = -fPIC
AWK = awk
all: static
.SUFFIXES: .c .o .lo
static: $(LIB) $(UTILS)
staticlib: $(LIB)
$(LIB): $(OBJS)
-rm -f $@
$(AR) rv $@ $(OBJS)
.c.o:
$(CC) $(CFLAGS) $(CDEFS) -c $<
shared: $(SOLIBV) $(SOUTILS)
sharedlib: $(SOLIBV)
$(SOLIBV): $(SOBJS)
$(CC) -shared -Wl,--soname,$(SOLIBV) -o $@ $(SOBJS)
$(SOLIB): $(SOLIBV)
rm -f $@
ln -s $(SOLIBV) $@
.c.lo:
$(CC) $(CFLAGS) $(PICFLAGS) $(CDEFS) -o $@ -c $<
# udns_codes.c is generated from udns.h
udns_codes.c: udns.h
@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)
rm -f $(SOBJS)
rm -f $(UOBJS)
rm -f build-stamp config.log
distclean: clean
rm -f $(LIBS) $(SOLIB) udns.3.html
rm -f $(UTILS) $(SOUTILS)
rm -f config.status config.h Makefile
Makefile: configure configure.lib Makefile.in
./configure
@echo
@echo Please rerun make >&2
@exit 1
.PHONY: all static staticlib shared sharedlib dist clean distclean subdist \
depend dep deps
depend dep deps: $(SRCS) $(USRC)
@echo Generating deps for:
@echo \ $(SRCS)
@echo \ $(USRCS)
@sed '/^# depend/q' Makefile.in > Makefile.tmp
@set -e; \
for f in $(SRCS) $(USRCS); do \
echo $${f%.c}.o $${f%.c}.lo: $$f \
`sed -n 's/^#[ ]*include[ ]*"\(.*\)".*/\1/p' $$f`; \
done >> Makefile.tmp; \
for f in $(USRCS:.c=.o); do \
echo "$${f%.?}: $$f \$$(LIB)"; \
echo " \$$(CC) \$$(CFLAGS) -o \$$@ $$f \$$(LIBFL)"; \
echo "$${f%.?}_s: $$f \$$(SOLIB)"; \
echo " \$$(CC) \$$(CFLAGS) -o \$$@ $$f \$$(SOLIBFL)"; \
done >> Makefile.tmp ; \
if cmp Makefile.tmp Makefile.in >/dev/null 2>&1 ; then \
echo Makefile.in unchanged; rm -f Makefile.tmp; \
else \
echo Updating Makfile.in; mv -f Makefile.tmp Makefile.in ; \
fi
# depend
udns_dn.o udns_dn.lo: udns_dn.c udns.h
udns_dntosp.o udns_dntosp.lo: udns_dntosp.c udns.h
udns_parse.o udns_parse.lo: udns_parse.c udns.h
udns_resolver.o udns_resolver.lo: udns_resolver.c config.h udns.h
udns_init.o udns_init.lo: udns_init.c config.h udns.h
udns_misc.o udns_misc.lo: udns_misc.c udns.h
udns_XtoX.o udns_XtoX.lo: udns_XtoX.c config.h udns.h inet_XtoX.c
udns_rr_a.o udns_rr_a.lo: udns_rr_a.c udns.h
udns_rr_ptr.o udns_rr_ptr.lo: udns_rr_ptr.c udns.h
udns_rr_mx.o udns_rr_mx.lo: udns_rr_mx.c udns.h
udns_rr_txt.o udns_rr_txt.lo: udns_rr_txt.c udns.h
udns_bl.o udns_bl.lo: udns_bl.c udns.h
udns_rr_srv.o udns_rr_srv.lo: udns_rr_srv.c udns.h
udns_rr_naptr.o udns_rr_naptr.lo: udns_rr_naptr.c udns.h
udns_codes.o udns_codes.lo: udns_codes.c udns.h
dnsget.o dnsget.lo: dnsget.c config.h udns.h getopt.c
rblcheck.o rblcheck.lo: rblcheck.c udns.h getopt.c
ex-rdns.o ex-rdns.lo: ex-rdns.c udns.h
dnsget: dnsget.o $(LIB)
$(CC) $(CFLAGS) -o $@ dnsget.o $(LIBFL)
dnsget_s: dnsget.o $(SOLIB)
$(CC) $(CFLAGS) -o $@ dnsget.o $(SOLIBFL)
rblcheck: rblcheck.o $(LIB)
$(CC) $(CFLAGS) -o $@ rblcheck.o $(LIBFL)
rblcheck_s: rblcheck.o $(SOLIB)
$(CC) $(CFLAGS) -o $@ rblcheck.o $(SOLIBFL)
ex-rdns: ex-rdns.o $(LIB)
$(CC) $(CFLAGS) -o $@ ex-rdns.o $(LIBFL)
ex-rdns_s: ex-rdns.o $(SOLIB)
$(CC) $(CFLAGS) -o $@ ex-rdns.o $(SOLIBFL)

85
deps/udns/NEWS

@ -0,0 +1,85 @@
$Id: NEWS,v 1.11 2007/01/15 21:19:08 mjt Exp $
User-visible changes in udns library. Recent changes on top.
0.0.9 (16 Jan 2007)
- incompat: minor API changes in dns_init() &friends. dns_init()
now requires extra `struct dns_ctx *' argument. Not bumped
soversion yet - I only expect one "release" with this change,
0.1 will have more changes and will increment so version
- many small bugfixes, here and there
- more robust FORMERR replies handling - not only such replies are now
recognized, but udns retries queries without EDNS0 extensions if tried
with, but server reported FORMERR
- portability changes, udns now includes getopt() implementation fo
the systems lacking it (mostly windows), and dns_ntop()&dns_pton(),
which are either just wrappers for system functions or reimplementations.
- build is now based on autoconf-like configuration
- NAPTR (RFC3403) RR decoding support
- new file NOTES which complements TODO somewhat, and includes some
important shortcomings
- many internal cleanups, including some preparations for better error
recovery, security and robustness (and thus API changes)
- removed some #defines which are now unused (like DNS_MAXSRCH)
- changed WIN32 to WINDOWS everywhere in preprocessor tests,
to be able to build it on win64 as well
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.

222
deps/udns/NOTES

@ -0,0 +1,222 @@
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). (Udns falls back to
non-EDNO0 query if EDNS0-enabled one received FORMERR or NOTIMPL error).
The problem is that with this, udns currently will not consider replies with
TC (truncation) bit set, and will treat such replies the same way as it
treats SERVFAIL replies, thus trying next server, or temp-failing the query
if no more servers to try. In other words, if the reply is really large, or
if the servers you're using don't support EDNS0, your application will be
unable to resolve a given name.
Yet it's not common situation - in practice, it's very rare.
Implementing TCP mode 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
~~~~~~~~~~~~~~~~~~~~~~~
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.
See also comments in udns_resolver.c, udns_newid().
And note that at least some other stub resolvers out there (like c-ares
for example) also uses sequential qID.
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...
CNAME recursion
~~~~~~~~~~~~~~~
Another interesting point 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.
Note also that standard gethostbyname() routine does not recurse in this
situation, too.
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 and how replies are handled.
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.
Another way to do the same is to manipulate query object right after a
query has been submitted, but before any events processing (during this
time, query object is allocated and initialized, but no actual network
packets were sent - it will happen on the next event processing). But
this way it become impossible to perform syncronous resolver calls, since
those calls hide query objects they use internally.
Speaking of replies handling - the planned change is to stop using dynamic
memory (malloc) inside the library. That is, instead of allocating a buffer
for a reply dynamically in a parsing routine (or memdup'ing the raw reply
packet if no parsing routine is specified), I want udns to return the packet
buffer it uses internally, and change parsing routines to expect a buffer
for result. When parsing, a routine will return true amount of memory it
will need to place the result, regardless of whenever it has enough room
or not, so that an application can (re)allocate properly sized buffer and
call a parsing routine again.
Another modification I plan to include is to have an ability to work in
terms of domain names (DNs) as used with on-wire DNS packets, not only
with asciiz representations of them. For this to work, the above two
changes (query submission and result passing) have to be completed first
(esp. the query submission part), so that it will be possible to specify
some additional query flags (for example) to request domain names instead
of the text strings, and to allow easy query submissions with either DNs
or text strings.

69
deps/udns/TODO

@ -0,0 +1,69 @@
$Id: TODO,v 1.13 2007/01/15 21:19:08 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?
(with now separate dns_init() and dns_reset(), it has finer
control, but still no way to init from system files but ignore
environment variables and the like)
* initialize/open the context automatically, and be more
liberal about initialization in general?
* dns_init(ctx, do_open) - make the parameter opposite, aka
dns_init(ctx, skip_open) ?
* allow TCP queue?
* And oh, qID should really be random. Or... not.
See notes in udns_resolver.c, dns_newid().
* 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.
Other folks done some more work in this area.

167
deps/udns/configure

@ -0,0 +1,167 @@
#! /bin/sh
# $Id: configure,v 1.4 2007/01/07 23:19:40 mjt Exp $
# autoconf-style configuration script
#
set -e
name=udns
if [ -f udns.h -a -f udns_resolver.c ] ; then :
else
echo "configure: error: sources not found at `pwd`" >&2
exit 1
fi
options="ipv6"
for opt in $options; do
eval enable_$opt=
done
if [ -f config.status ]; then
. ./config.status
fi
enable() {
opt=`echo "$1" | sed 's/^--[^-]*-//'`
case "$opt" in
ipv6|stats|master_dump|zlib|dso) ;;
master-dump) opt=master_dump ;;
*) echo "configure: unrecognized option \`$1'" >&2; exit 1;;
esac
eval enable_$opt=$2
}
while [ $# -gt 0 ]; do
case "$1" in
--disable-*|--without-*|--no-*) enable "$1" n;;
--enable-*|--with-*) enable "$1" y;;
--help | --hel | --he | --h | -help | -hel | -he | -h )
cat <<EOF
configure: configure $name package.
Usage: ./configure [options]
where options are:
--enable-option, --with-option --
enable the named option/feature
--disable-option, --without-option, --no-option --
disable the named option/feature
--help - print this help and exit
Optional features (all enabled by default if system supports a feature):
ipv6 - enable/disable IP version 6 (IPv6) support
EOF
exit 0
;;
*) echo "configure: unknown option \`$1'" >&2; exit 1 ;;
esac
shift
done
. ./configure.lib
ac_msg "configure"
ac_result "$name package"
ac_prog_c_compiler_v
ac_prog_ranlib_v
ac_ign ac_yesno "for getopt()" ac_have GETOPT ac_link <<EOF
#include <stdio.h>
extern int optind;
extern char *optarg;
extern int getopt(int, char **, char *);
int main(int argc, char **argv) {
getopt(argc, argv, "abc");
return optarg ? optind : 0;
}
EOF
ac_ign \
ac_yesno "for inet_pton() && inet_ntop()" \
ac_have INET_PTON_NTOP \
ac_link <<EOF
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main() {
char buf[64];
long x = 0;
inet_pton(AF_INET, &x, buf);
return inet_ntop(AF_INET, &x, buf, sizeof(buf));
}
EOF
if ac_yesno "for socklen_t" ac_compile <<EOF
#include <sys/types.h>
#include <sys/socket.h>
int foo() { socklen_t len; len = 0; return len; }
EOF
then :
else
ac_define socklen_t int
fi
if ac_library_find_v 'socket and connect' "" "-lsocket -lnsl" <<EOF
int main() { socket(); connect(); return 0; }
EOF
then :
else
ac_fatal "cannot find libraries needed for sockets"
fi
if [ n != "$enable_ipv6" ]; then
if ac_yesno "for IPv6" ac_have IPv6 ac_compile <<EOF
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
struct sockaddr_in6 sa;
sa.sin6_family = AF_INET6;
return 0;
}
EOF
then :
elif [ "$enable_ipv6" ]; then
ac_fatal "IPv6 is requested but not available"
fi
fi # !disable_ipv6?
if ac_yesno "for poll()" ac_have POLL ac_link <<EOF
#include <sys/types.h>
#include <sys/poll.h>
int main() {
struct pollfd pfd[2];
return poll(pfd, 2, 10);
}
EOF
then :
else
ac_ign ac_yesno "for sys/select.h" ac_have SYS_SELECT_H ac_cpp <<EOF
#include <sys/types.h>
#include <sys/select.h>
EOF
fi
ac_config_h
ac_output Makefile
ac_msg "creating config.status"
rm -f config.status
{
echo "# automatically generated by configure to hold command-line options"
echo
found=
for opt in $options; do
eval val=\$enable_$opt
if [ -n "$val" ]; then
echo enable_$opt=$val
found=y
fi
done
if [ ! "$found" ]; then
echo "# (no options encountered)"
fi
} > config.status
ac_result ok
ac_result "all done."
exit 0

268
deps/udns/configure.lib

@ -0,0 +1,268 @@
# configure.lib
# a library of shell routines for simple autoconf system
#
set -e
ac_substitutes=
rm -f conftest* config.log
exec 5>config.log
cat <<EOF >&5
This file contains any messages produced by compilers etc while
running configure, to aid debugging if configure script makes a mistake.
EOF
case `echo "a\c"` in
*c*) ac_en=-n ac_ec= ;;
*) ac_en= ac_ec='\c' ;;
esac
##### Messages
ac_msg() {
echo $ac_en "$*... $ac_ec"
echo ">>> $*" >&5
}
ac_checking() {
echo $ac_en "checking $*... $ac_ec"
echo ">>> checking $*" >&5
}
ac_result() {
echo "$1"
echo "=== $1" >&5
}
ac_fatal() {
echo "configure: fatal: $*" >&2
echo "=== FATAL: $*" >&5
exit 1
}
ac_warning() {
echo "configure: warning: $*" >&2
echo "=== WARNING: $*" >&5
}
ac_ign() {
"$@" || :
}
# ac_run command...
# captures output in conftest.out
ac_run() {
# apparently UnixWare (for one) /bin/sh optimizes the following "if"
# "away", by checking if there's such a command BEFORE redirecting
# output. So error message (like "gcc: command not found") goes
# to stderr instead of to conftest.out, and `cat conftest.out' below
# fails.
if "$@" >conftest.out 2>&1; then
return 0
else
echo "==== Command invocation failed. Command line was:" >&5
echo "$*" >&5
echo "==== compiler input was:" >&5
cat conftest.c >&5
echo "==== output was:" >&5
cat conftest.out >&5
echo "====" >&5
return 1
fi
}
# common case for ac_verbose: yes/no result
ac_yesno() {
ac_checking "$1"
shift
if "$@"; then
ac_result yes
return 0
else
ac_result no
return 1
fi
}
ac_subst() {
ac_substitutes="$ac_substitutes $*"
}
ac_define() {
CDEFS="$CDEFS -D$1=${2:-1}"
}
ac_have() {
ac_what=$1; shift
if "$@"; then
ac_define HAVE_$ac_what
eval ac_have_$ac_what=yes
return 0
else
eval ac_have_$ac_what=no
return 1
fi
}
##### Compiling, linking
# run a compiler
ac_run_compiler() {
rm -f conftest*; cat >conftest.c
ac_run $CC $CFLAGS $CDEFS "$@" conftest.c
}
ac_compile() {
ac_run_compiler -c
}
ac_link() {
ac_run_compiler -o conftest $LIBS "$@"
}
ac_cpp() {
ac_run_compiler -E "$@"
}
### check for C compiler. Set $CC, $CFLAGS etc
ac_prog_c_compiler_v() {
ac_checking "for C compiler"
rm -f conftest*
echo 'int main(int argc, char **argv) { return 0; }' >conftest.c
if [ -n "$CC" ]; then
if ac_run $CC -o conftest conftest.c && ac_run ./conftest; then
ac_result "\$CC ($CC)"
else
ac_result no
ac_fatal "\$CC ($CC) is not a working compiler"
fi
else
for cc in gcc cc ; do
if ac_run $cc -o conftest conftest.c && ac_run ./conftest; then
ac_result "$cc"
CC=$cc
break
fi
done
if [ -z "$CC" ]; then
ac_result no
ac_fatal "no working C compiler found in \$PATH. please set \$CC variable"
fi
fi
if [ -z "$CFLAGS" ]; then
if ac_yesno "whenever C compiler ($CC) is GNU CC" \
ac_grep_cpp yEs_mAsTeR <<EOF
#ifdef __GNUC__
yEs_mAsTeR;
#endif
EOF
then
CFLAGS="-Wall -W -O2 -pipe"
else
CFLAGS=-O
fi
fi
cc="$CC $CFLAGS"
ccld="$cc"
if [ -n "$LDFLAGS" ]; then ccld="$ccld $LDFLAGS"; fi
if [ -n "$LIBS" ]; then ccld="$ccld $LIBS"; fi
if ac_yesno "whenever the C compiler ($ccld)
can produce executables" \
ac_compile_run <<EOF
int main() { return 0; }
EOF
then :
else
ac_fatal "no working C compiler found"
fi
LD='$(CC)'
[ -n "$AR" ] || AR=ar
[ -n "$ARFLAGS" ] || ARFLAGS=rv
[ -n "$AWK" ] || AWK=awk
ac_substitutes="$ac_substitutes CC CFLAGS CDEFS LD LDFLAGS LIBS AR ARFLAGS AWK"
}
ac_prog_ranlib_v() {
ac_checking "for ranlib"
if [ -n "$RANLIB" ]; then
ac_result "\$RANLIB ($RANLIB)"
else
ifs="$IFS"
IFS=:
for dir in $PATH; do
[ -n "$dir" ] || dir=.
if [ -f $dir/ranlib ]; then
RANLIB=ranlib
break
fi
done
IFS="$ifs"
if [ -z "$RANLIB" ]; then ac_result no; RANLIB=:
else ac_result "$RANLIB"
fi
fi
ac_substitutes="$ac_substitutes RANLIB"
}
ac_library_find_v() {
ac_checking "for libraries needed for $1"
shift
fond=
rm -f conftest*; cat >conftest.c
for lib in "$@"; do
if ac_run $CC $CFLAGS $LDFLAGS conftest.c -o conftest $LIBS $lib; then
found=y
break
fi
done
if [ ! "$found" ]; then
ac_result "not found"
return 1
fi
if [ -z "$lib" ]; then
ac_result "ok (none needed)"
else
ac_result "ok ($lib)"
LIBS="$LIBS $lib"
fi
}
ac_compile_run() {
ac_link "$@" && ac_run ./conftest
}
ac_grep_cpp() {
pattern="$1"; shift
ac_cpp "$@" && grep "$pattern" conftest.out >/dev/null
}
ac_output() {
for var in $ac_substitutes; do
eval echo "\"s|@$var@|\$$var|\""
done >conftest.sed
for file in "$@"; do
ac_msg "creating $file"
if [ -f $file.in ]; then
sed -f conftest.sed $file.in > $file.tmp
mv -f $file.tmp $file
ac_result ok
else
ac_result failed
ac_fatal "$file.in not found"
fi
done
rm -f conftest*
}
ac_config_h() {
h=${1:-config.h}
ac_msg "creating $h"
rm -f $1.tmp
echo "/* automatically generated by configure. */" > $h.tmp
echo "$CDEFS" | tr ' ' '
' | sed -e 's/^-D/#define /' -e 's/=/ /' >> $h.tmp
if [ -f $h ] && cmp -s $h.tmp $h ; then
rm -f $h.tmp
ac_result unchanged
else
mv -f $h.tmp $h
ac_result ok
fi
CDEFS=-DHAVE_CONFIG_H
}

136
deps/udns/debian/changelog

@ -0,0 +1,136 @@
udns (0.0.9) 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
* reworked initialisation stuff. Minor API changes -- new dns_reset(),
dns_init() now has one more argument, corrections to dns_close(),
dns_open(), dns_free(). Cleaned up *_internal() routines.
* moved dns_init() routine into separate file.
* reworked dn suffix searching. As a result, query only has
dnsq_dn[] field -- no header and EDNS0 "suffix", and query
packet is now formatted in dns_send()
* added inet_XtoX.c - public domain implementations of inet_pton()
and inet_ntop(), inet_aton() and inet_ntoa() routines.
* added getopt.c - public domain implementation of getopt() routine.
* switched to autoconf-style configuration
* introduce dns_random16() to generate query IDs
(currently based on gettimeofday.tv_usec)
* dnsget: fix printing of -t ANY and -c any records,
thanks to Jaroslaw Rafa
* implement dns_ntop() and dns_pton() as either wrappers or
reimplementations (using inet_XtoX.c) of inet_ntop() and inet_pton().
Too much troubles with portability - it was a complete mess, each
OS has its own problems with them.
And use those routines everywhere.
* s/WIN32/WINDOWS/g to allow building on WIN64. Oh well.
* try to find query by ID first, don't drop header-only replies early.
This is in order to support FORMERR replies from nameservers which
don't understand EDNS0.
* retry queries w/o EDNS0 if sent with it and if
server reported FORMERR or NOTIMPL
* fixed debian/copyright and debian/control
* rblcheck revamp
-- Michael Tokarev <mjt@corpit.ru> Tue, 16 Jan 2007 00:00:28 +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@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@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@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@corpit.ru> Thu, 7 Apr 2005 00:05:24 +0400
Local variables:
mode: debian-changelog
End:

33
deps/udns/debian/control

@ -0,0 +1,33 @@
Source: udns
Priority: optional
Maintainer: Michael Tokarev <mjt@corpit.ru>
Build-Depends: debhelper (>= 4.0.0)
Standards-Version: 3.7.2
Package: libudns0
Section: libs
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: libdevel
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

23
deps/udns/debian/copyright

@ -0,0 +1,23 @@
This is udns, written and maintained by Michael Tokarev <mjt@corpit.ru>
The original source can always be found at:
http://www.corpit.ru/mjt/udns.html
Copyright (C) 2005,2006,2007 Michael Tokarev
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
General Lesser 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
On Debian systems, the complete text of the GNU Lesser General
Public License can be found in `/usr/share/common-licenses/LGPL'.

93
deps/udns/debian/rules

@ -0,0 +1,93 @@
#!/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
config.h: ./configure Makefile.in
dh_testdir
./configure --enable-ipv6
build: build-stamp
build-stamp: config.h
dh_testdir
$(MAKE) CFLAGS="$(CFLAGS)" SOVER=$(SOVER) \
staticlib sharedlib rblcheck_s dnsget_s
mv -f dnsget_s dnsget
mv -f rblcheck_s rblcheck
mv -f libudns_s.so libudns.so
echo
touch $@
clean:
dh_testdir
rm -f build-stamp
if [ -f Makefile ]; then $(MAKE) distclean; fi
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_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 -V
dh_installdeb
dh_shlibdeps -L libudns$(SOVER) -l .
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install

182
deps/udns/dnsget.1

@ -0,0 +1,182 @@
.\" $Id: dnsget.1,v 1.3 2005/04/20 00:55:34 mjt Exp $
.\" dnsget manpage
.\"
.\" Copyright (C) 2005 Michael Tokarev <mjt@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).

726
deps/udns/dnsget.c

@ -0,0 +1,726 @@
/* $Id: dnsget.c,v 1.31 2007/01/08 01:14:44 mjt Exp $
simple host/dig-like application using UDNS library
Copyright (C) 2005 Michael Tokarev <mjt@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 WINDOWS
#include <windows.h>
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <unistd.h>
#endif
#include <time.h>
#include <stdarg.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "udns.h"
#ifndef HAVE_GETOPT
# include "getopt.c"
#endif
#ifndef AF_INET6
# define AF_INET6 10
#endif
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);
}
static const char *dns_xntop(int af, const void *src) {
static char buf[6*5+4*4];
return dns_ntop(af, src, buf, sizeof(buf));
}
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", dns_xntop(AF_INET6, dptr));
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", dns_xntop(AF_INET, 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))
printf("%s port %d\n",
dns_xntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr),
htons(((struct sockaddr_in*)sa)->sin_port));
#ifdef HAVE_IPv6
else if (sa->sa_family == AF_INET6 && slen >= sizeof(struct sockaddr_in6))
printf("%s port %d\n",
dns_xntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr),
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 == DNS_T_ANY ? 0 : q->qtyp;
p.dnsp_qcls = qcls == DNS_C_ANY ? 0 : 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(NULL, 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, AAA, 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 (dns_pton(AF_INET, ns[i], &sin.sin_addr) <= 0) {
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",
dns_xntop(AF_INET, &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 (dns_pton(AF_INET, name, &a.addr) > 0) {
dns_a4todn(&a.addr, 0, dn, sizeof(dn));
l_qtyp = DNS_T_PTR;
abs = 1;
}
#ifdef HAVE_IPv6
else if (dns_pton(AF_INET6, name, &a.addr6) > 0) {
dns_a6todn(&a.addr6, 0, dn, sizeof(dn));
l_qtyp = DNS_T_PTR;
abs = 1;
}
#endif
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;
}

113
deps/udns/ex-rdns.c

@ -0,0 +1,113 @@
/* $Id: ex-rdns.c,v 1.8 2007/01/07 22:46:47 mjt Exp $
parallel rDNS resolver example - read IP addresses from stdin,
write domain names to stdout
Copyright (C) 2005 Michael Tokarev <mjt@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 <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(NULL, 1) < 0) {
fprintf(stderr, "unable to initialize dns library\n");
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 (dns_pton(AF_INET, linebuf, &pa.a) <= 0)
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;
}

165
deps/udns/getopt.c

@ -0,0 +1,165 @@
/* $Id: getopt.c,v 1.2 2007/01/07 23:19:19 mjt Exp $
* Simple getopt() implementation.
*
* Standard interface:
* extern int getopt(int argc, char *const *argv, const char *opts);
* extern int optind; current index in argv[]
* extern char *optarg; argument for the current option
* extern int optopt; the current option
* extern int opterr; to control error printing
*
* Some minor extensions:
* ignores leading `+' sign in opts[] (unemplemented GNU extension)
* handles optional arguments, in form "x::" in opts[]
* if opts[] starts with `:', will return `:' in case of missing required
* argument, instead of '?'.
*
* Compile with -DGETOPT_NO_OPTERR to never print errors internally.
* Compile with -DGETOPT_NO_STDIO to use write() calls instead of fprintf() for
* error reporting (ignored with -DGETOPT_NO_OPTERR).
* Compile with -DGETOPT_CLASS=static to get static linkage.
* Compile with -DGETOPT_MY to redefine all visible symbols to be prefixed
* with "my_", like my_getopt instead of getopt.
* Compile with -DTEST to get a test executable.
*
* Written by Michael Tokarev. Public domain.
*/
#include <string.h>
#ifndef GETOPT_CLASS
# define GETOPT_CLASS
#endif
#ifdef GETOPT_MY
# define optarg my_optarg
# define optind my_optind
# define opterr my_opterr
# define optopt my_optopt
# define getopt my_getopt
#endif
GETOPT_CLASS char *optarg /* = NULL */;
GETOPT_CLASS int optind = 1;
GETOPT_CLASS int opterr = 1;
GETOPT_CLASS int optopt;
static char *nextc /* = NULL */;
#if defined(GETOPT_NO_OPTERR)
#define printerr(argv, msg)
#elif defined(GETOPT_NO_STDIO)
extern int write(int, void *, int);
static void printerr(char *const *argv, const char *msg) {
if (opterr) {
char buf[64];
unsigned pl = strlen(argv[0]);
unsigned ml = strlen(msg);
char *p;
if (pl + /*": "*/2 + ml + /*" -- c\n"*/6 > sizeof(buf)) {
write(2, argv[0], pl);
p = buf;
}
else {
memcpy(buf, argv[0], ml);
p = buf + pl;
}
*p++ = ':'; *p++ = ' ';
memcpy(p, msg, ml); p += ml;
*p++ = ' '; *p++ = '-'; *p++ = '-'; *p++ = ' ';
*p++ = optopt;
*p++ = '\n';
write(2, buf, p - buf);
}
}
#else
#include <stdio.h>
static void printerr(char *const *argv, const char *msg) {
if (opterr)
fprintf(stderr, "%s: %s -- %c\n", argv[0], msg, optopt);
}
#endif
GETOPT_CLASS int getopt(int argc, char *const *argv, const char *opts) {
char *p;
optarg = 0;
if (*opts == '+') /* GNU extension (permutation) - isn't supported */
++opts;
if (!optind) { /* a way to reset things */
nextc = 0;
optind = 1;
}
if (!nextc || !*nextc) { /* advance to the next argv element */
/* done scanning? */
if (optind >= argc)
return -1;
/* not an optional argument */
if (argv[optind][0] != '-')
return -1;
/* bare `-' */
if (argv[optind][1] == '\0')
return -1;
/* special case `--' argument */
if (argv[optind][1] == '-' && argv[optind][2] == '\0') {
++optind;
return -1;
}
nextc = argv[optind] + 1;
}
optopt = *nextc++;
if (!*nextc)
++optind;
p = strchr(opts, optopt);
if (!p || optopt == ':') {
printerr(argv, "illegal option");
return '?';
}
if (p[1] == ':') {
if (*nextc) {
optarg = nextc;
nextc = NULL;
++optind;
}
else if (p[2] != ':') { /* required argument */
if (optind >= argc) {
printerr(argv, "option requires an argument");
return *opts == ':' ? ':' : '?';
}
else
optarg = argv[optind++];
}
}
return optopt;
}
#ifdef TEST
#include <stdio.h>
int main(int argc, char **argv) {
int c;
while((c = getopt(argc, argv, "ab:c::")) != -1) switch(c) {
case 'a':
case 'b':
case 'c':
printf("option %c %s\n", c, optarg ? optarg : "(none)");
break;
default:
return -1;
}
for(c = optind; c < argc; ++c)
printf("non-opt: %s\n", argv[c]);
return 0;
}
#endif

327
deps/udns/inet_XtoX.c

@ -0,0 +1,327 @@
/* $Id: inet_XtoX.c,v 1.1 2006/12/04 01:55:39 mjt Exp $
* Simple implementation of the following functions:
* inet_ntop(), inet_ntoa(), inet_pton(), inet_aton().
*
* Differences from traditional implementaitons:
* o modifies destination buffers even on error return.
* o no fancy (hex, or 1.2) input support in inet_aton()
* o inet_aton() does not accept junk after an IP address.
* o inet_ntop(AF_INET) requires at least 16 bytes in dest,
* and inet_ntop(AF_INET6) at least 40 bytes
* (traditional inet_ntop() will try to fit anyway)
*
* Compile with -Dinet_XtoX_prefix=pfx_ to have pfx_*() instead of inet_*()
* Compile with -Dinet_XtoX_no_ntop or -Dinet_XtoX_no_pton
* to disable net2str or str2net conversions.
*
* #define inet_XtoX_prototypes and #include "this_file.c"
* to get function prototypes only (but not for inet_ntoa()).
* #define inet_XtoX_decl to be `static' for static visibility,
* or use __declspec(dllexport) or somesuch...
*
* Compile with -DTEST to test against stock implementation.
*
* Written by Michael Tokarev. Public domain.
*/
#ifdef inet_XtoX_prototypes
struct in_addr;
#else
#include <errno.h>
#ifdef TEST
# include <netinet/in.h>
# include <sys/socket.h>
# include <arpa/inet.h>
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <string.h>
# undef inet_XtoX_prefix
# define inet_XtoX_prefix mjt_inet_
# undef inet_XtoX_no_ntop
# undef inet_XtoX_no_pton
#else /* !TEST */
struct in_addr { /* declare it here to avoid messing with headers */
unsigned char x[4];
};
#endif /* TEST */
#endif /* inet_XtoX_prototypes */
#ifndef inet_XtoX_prefix
# define inet_XtoX_prefix inet_
#endif
#ifndef inet_XtoX_decl
# define inet_XtoX_decl /*empty*/
#endif
#define cc2_(x,y) cc2__(x,y)
#define cc2__(x,y) x##y
#define fn(x) cc2_(inet_XtoX_prefix,x)
#ifndef inet_XtoX_no_ntop
inet_XtoX_decl const char *
fn(ntop)(int af, const void *src, char *dst, unsigned size);
#ifndef inet_XtoX_prototypes
static int mjt_ntop4(const void *_src, char *dst, int size) {
unsigned i, x, r;
char *p;
const unsigned char *s = _src;
if (size < 4*4) /* for simplicity, disallow non-max-size buffer */
return 0;
for (i = 0, p = dst; i < 4; ++i) {
if (i) *p++ = '.';
x = r = s[i];
if (x > 99) { *p++ = (char)(r / 100 + '0'); r %= 100; }
if (x > 9) { *p++ = (char)(r / 10 + '0'); r %= 10; }
*p++ = (char)(r + '0');
}
*p = '\0';
return 1;
}
static char *hexc(char *p, unsigned x) {
static char hex[16] = "0123456789abcdef";
if (x > 0x0fff) *p++ = hex[(x >>12) & 15];
if (x > 0x00ff) *p++ = hex[(x >> 8) & 15];
if (x > 0x000f) *p++ = hex[(x >> 4) & 15];
*p++ = hex[x & 15];
return p;
}
static int mjt_ntop6(const void *_src, char *dst, int size) {
unsigned i;
unsigned short w[8];
unsigned bs = 0, cs = 0;
unsigned bl = 0, cl = 0;
char *p;
const unsigned char *s = _src;
if (size < 40) /* for simplicity, disallow non-max-size buffer */
return 0;
for(i = 0; i < 8; ++i, s += 2) {
w[i] = (((unsigned short)(s[0])) << 8) | s[1];
if (!w[i]) {
if (!cl++) cs = i;
}
else {
if (cl > bl) bl = cl, bs = cs;
}
}
if (cl > bl) bl = cl, bs = cs;
p = dst;
if (bl == 1)
bl = 0;
if (bl) {
for(i = 0; i < bs; ++i) {
if (i) *p++ = ':';
p = hexc(p, w[i]);
}
*p++ = ':';
i += bl;
if (i == 8)
*p++ = ':';
}
else
i = 0;
for(; i < 8; ++i) {
if (i) *p++ = ':';
if (i == 6 && !bs && (bl == 6 || (bl == 5 && w[5] == 0xffff)))
return mjt_ntop4(s - 4, p, size - (p - dst));
p = hexc(p, w[i]);
}
*p = '\0';
return 1;
}
inet_XtoX_decl const char *
fn(ntop)(int af, const void *src, char *dst, unsigned size) {
switch(af) {
/* don't use AF_*: don't mess with headers */
case 2: /* AF_INET */ if (mjt_ntop4(src, dst, size)) return dst; break;
case 10: /* AF_INET6 */ if (mjt_ntop6(src, dst, size)) return dst; break;
default: errno = EAFNOSUPPORT; return (char*)0;
}
errno = ENOSPC;
return (char*)0;
}
inet_XtoX_decl const char *
fn(ntoa)(struct in_addr addr) {
static char buf[4*4];
mjt_ntop4(&addr, buf, sizeof(buf));
return buf;
}
#endif /* inet_XtoX_prototypes */
#endif /* inet_XtoX_no_ntop */
#ifndef inet_XtoX_no_pton
inet_XtoX_decl int fn(pton)(int af, const char *src, void *dst);
inet_XtoX_decl int fn(aton)(const char *src, struct in_addr *addr);
#ifndef inet_XtoX_prototypes
static int mjt_pton4(const char *c, void *dst) {
unsigned char *a = dst;
unsigned n, o;
for (n = 0; n < 4; ++n) {
if (*c < '0' || *c > '9')
return 0;
o = *c++ - '0';
while(*c >= '0' && *c <= '9')
if ((o = o * 10 + (*c++ - '0')) > 255)
return 0;
if (*c++ != (n == 3 ? '\0' : '.'))
return 0;
*a++ = (unsigned char)o;
}
return 1;
}
static int mjt_pton6(const char *c, void *dst) {
unsigned short w[8], *a = w, *z, *i;
unsigned v, o;
const char *sc;
unsigned char *d = dst;
if (*c != ':') z = (unsigned short*)0;
else if (*++c != ':') return 0;
else ++c, z = a;
i = 0;
for(;;) {
v = 0;
sc = c;
for(;;) {
if (*c >= '0' && *c <= '9') o = *c - '0';
else if (*c >= 'a' && *c <= 'f') o = *c - 'a' + 10;
else if (*c >= 'A' && *c <= 'F') o = *c - 'A' + 10;
else break;
v = (v << 4) | o;
if (v > 0xffff) return 0;
++c;
}
if (sc == c) {
if (z == a && !*c)
break;
else
return 0;
}
if (*c == ':') {
if (a >= w + 8)
return 0;
*a++ = v;
if (*++c == ':') {
if (z)
return 0;
z = a;
if (!*++c)
break;
}
}
else if (!*c) {
if (a >= w + 8)
return 0;
*a++ = v;
break;
}
else if (*c == '.') {
if (a > w + 6)
return 0;
if (!mjt_pton4(sc, d))
return 0;
*a++ = ((unsigned)(d[0]) << 8) | d[1];
*a++ = ((unsigned)(d[2]) << 8) | d[3];
break;
}
else
return 0;
}
v = w + 8 - a;
if ((v && !z) || (!v && z))
return 0;
for(i = w; ; ++i) {
if (i == z)
while(v--) { *d++ = '\0'; *d++ = '\0'; }
if (i >= a)
break;
*d++ = (unsigned char)((*i >> 8) & 255);
*d++ = (unsigned char)(*i & 255);
}
return 1;
}
inet_XtoX_decl int fn(pton)(int af, const char *src, void *dst) {
switch(af) {
/* don't use AF_*: don't mess with headers */
case 2 /* AF_INET */: return mjt_pton4(src, dst);
case 10 /* AF_INET6 */: return mjt_pton6(src, dst);
default: errno = EAFNOSUPPORT; return -1;
}
}
inet_XtoX_decl int fn(aton)(const char *src, struct in_addr *addr) {
return mjt_pton4(src, addr);
}
#endif /* inet_XtoX_prototypes */
#endif /* inet_XtoX_no_pton */
#ifdef TEST
int main(int argc, char **argv) {
int i;
char n0[16], n1[16];
char p0[64], p1[64];
int af = AF_INET;
int pl = sizeof(p0);
int r0, r1;
const char *s0, *s1;
while((i = getopt(argc, argv, "46a:p:")) != EOF) switch(i) {
case '4': af = AF_INET; break;
case '6': af = AF_INET6; break;
case 'a': case 'p': pl = atoi(optarg); break;
default: return 1;
}
for(i = optind; i < argc; ++i) {
char *a = argv[i];
printf("%s:\n", a);
r0 = inet_pton(af, a, n0);
printf(" p2n stock: %s\n",
(r0 < 0 ? "(notsupp)" : !r0 ? "(inval)" : fn(ntop)(af,n0,p0,sizeof(p0))));
r1 = fn(pton)(af, a, n1);
printf(" p2n this : %s\n",
(r1 < 0 ? "(notsupp)" : !r1 ? "(inval)" : fn(ntop)(af,n1,p1,sizeof(p1))));
if ((r0 > 0) != (r1 > 0) ||
(r0 > 0 && r1 > 0 && memcmp(n0, n1, af == AF_INET ? 4 : 16) != 0))
printf(" DIFFER!\n");
s0 = inet_ntop(af, n1, p0, pl);
printf(" n2p stock: %s\n", s0 ? s0 : "(inval)");
s1 = fn(ntop)(af, n1, p1, pl);
printf(" n2p this : %s\n", s1 ? s1 : "(inval)");
if ((s0 != 0) != (s1 != 0) ||
(s0 && s1 && strcmp(s0, s1) != 0))
printf(" DIFFER!\n");
}
return 0;
}
#endif /* TEST */

151
deps/udns/rblcheck.1

@ -0,0 +1,151 @@
.\" $Id: rblcheck.1,v 1.1 2005/04/24 23:14:23 mjt Exp $
.\" rblckeck manpage
.\"
.\" Copyright (C) 2005 Michael Tokarev <mjt@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.

377
deps/udns/rblcheck.c

@ -0,0 +1,377 @@
/* $Id: rblcheck.c,v 1.14 2007/01/10 02:52:51 mjt Exp $
dnsbl (rbl) checker application
Copyright (C) 2005 Michael Tokarev <mjt@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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WINDOWS
# include <winsock2.h>
#else
# include <unistd.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
#endif
#include <time.h>
#include <errno.h>
#include <stdarg.h>
#include "udns.h"
#ifndef HAVE_GETOPT
# include "getopt.c"
#endif
static const char *version = "udns-rblcheck 0.2";
static char *progname;
static void error(int die, const char *fmt, ...) {
va_list ap;
fprintf(stderr, "%s: ", progname);
va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap);
putc('\n', stderr);
fflush(stderr);
if (die)
exit(1);
}
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)
error(1, "out of memory");
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) {
char buf[4*4];
error(0, "unable to %s for %s (%s): %s",
what, dns_ntop(AF_INET, &ipl->key, buf, sizeof(buf)),
ipl->zone, dns_strerror(dns_status(0)));
++failures;
}
static void display_result(struct ipcheck *ipc) {
int j;
struct rblookup *l, *le;
char buf[4*4];
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) {
dns_ntop(AF_INET, &l->key, buf, sizeof(buf));
if (ipc->name) printf("%s[%s]", ipc->name, buf);
else printf("%s", buf);
}
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 ? " " : "",
dns_ntop(AF_INET, &l->addr->dnsa4_addr[j], buf, sizeof(buf)));
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 {
error(0, "unable to lookup `%s': %s",
ipc->name, dns_strerror(dns_status(ctx)));
++failures;
}
}
static int submit(struct ipcheck *ipc) {
struct in_addr addr;
if (dns_pton(AF_INET, ipc->name, &addr) > 0) {
submit_a_queries(ipc, 1, &addr);
ipc->name = NULL;
}
else if (!dns_submit_a4(0, ipc->name, 0, namecb, ipc)) {
error(0, "unable to submit name query for %s: %s\n",
ipc->name, dns_strerror(dns_status(0)));
++failures;
}
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;
error(1, "unable to read zonefile `%s'", optarg);
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 (udns library version %s).\n",
progname, version, dns_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:
error(1, "use `%s -h' for help", progname);
}
if (!zgiven) {
char *s = getenv("RBLCHECK_ZONES");
if (s) {
char *k;
s = strdup(s);
for(k = strtok(s, " \t"); k; k = strtok(NULL, " \t"))
addzone(k);
free(s);
}
else { /* probably worthless on windows? */
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)
error(1, "no service (zone) list specified (-s or -S option)");
argv += optind;
argc -= optind;
if (!argc)
return 0;
if (dns_init(NULL, 0) < 0)
error(1, "unable to initialize DNS library: %s", strerror(errno));
if (nameserver) {
dns_add_serv(NULL, NULL);
if (dns_add_serv(NULL, nameserver) < 0)
error(1, "wrong IP address for a nameserver: `%s'", nameserver);
}
if (dns_open(NULL) < 0)
error(1, "unable to initialize DNS library: %s", strerror(errno));
for (c = 0; c < argc; ++c) {
if (c && (verbose > 1 || (verbose == 1 && do_txt))) putchar('\n');
memset(&ipc, 0, sizeof(ipc));
ipc.name = argv[c];
submit(&ipc);
waitdns(&ipc);
display_result(&ipc);
if (stopfirst > 1 && listed) break;
}
return listed ? 100 : failures ? 2 : 0;
}

1351
deps/udns/udns.3

File diff suppressed because it is too large

745
deps/udns/udns.h

@ -0,0 +1,745 @@
/* $Id: udns.h,v 1.51 2007/01/15 21:19:08 mjt Exp $
header file for the UDNS library.
Copyright (C) 2005 Michael Tokarev <mjt@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.9"
#ifdef WINDOWS
# 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_DNPAD 1 /* padding for DN buffers */
#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_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);
/* either wrappers or reimplementations for inet_ntop() and inet_pton() */
UDNS_API const char *dns_ntop(int af, const void *src, char *dst, int size);
UDNS_API int dns_pton(int af, const char *src, void *dst);
/**************************************************************************/
/**************** 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++ = (dnsc_t)((n >> 8) & 255); *d++ = (dnsc_t)(n & 255); return d;
}
static __inline dnsc_t *dns_put32(dnsc_t *d, unsigned n) {
*d++ = (dnsc_t)((n >> 24) & 255); *d++ = (dnsc_t)((n >> 16) & 255);
*d++ = (dnsc_t)((n >> 8) & 255); *d++ = (dnsc_t)(n & 255);
return d;
}
/* return pseudo-random 16bits number */
UDNS_API unsigned dns_random16(void);
/* 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;
/* reset resolver context to default state, close it if open, drop queries */
UDNS_API void
dns_reset(struct dns_ctx *ctx);
/* reset resolver context and read in system configuration */
UDNS_API int
dns_init(struct dns_ctx *ctx, 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 returned by dns_new(); 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 structure (with ports) */
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 */
};
/* 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 */

50
deps/udns/udns_XtoX.c

@ -0,0 +1,50 @@
/* $Id: udns_XtoX.c,v 1.1 2007/01/07 22:20:39 mjt Exp $
udns_ntop() and udns_pton() routines, which are either
- wrappers for inet_ntop() and inet_pton() or
- reimplementations of those routines.
Copyright (C) 2005 Michael Tokarev <mjt@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
#include "udns.h"
#ifdef HAVE_INET_PTON_NTOP
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
const char *dns_ntop(int af, const void *src, char *dst, int size) {
return inet_ntop(af, src, dst, size);
}
int dns_pton(int af, const char *src, void *dst) {
return inet_pton(af, src, dst);
}
#else
#define inet_XtoX_prefix udns_
#include "inet_XtoX.c"
#endif

160
deps/udns/udns_bl.c

@ -0,0 +1,160 @@
/* $Id: udns_bl.c,v 1.10 2005/09/12 10:55:21 mjt Exp $
DNSBL stuff
Copyright (C) 2005 Michael Tokarev <mjt@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));
}

382
deps/udns/udns_dn.c

@ -0,0 +1,382 @@
/* $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@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 */

30
deps/udns/udns_dntosp.c

@ -0,0 +1,30 @@
/* $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@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;
}

231
deps/udns/udns_init.c

@ -0,0 +1,231 @@
/* $Id: udns_init.c,v 1.6 2007/01/08 00:41:38 mjt Exp $
resolver initialisation stuff
Copyright (C) 2006 Michael Tokarev <mjt@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 WINDOWS
# include <winsock2.h> /* includes <windows.h> */
# include <iphlpapi.h> /* for dns server addresses etc */
#else
# include <sys/types.h>
# include <unistd.h>
# include <fcntl.h>
#endif /* !WINDOWS */
#include <stdlib.h>
#include <string.h>
#include "udns.h"
#define ISSPACE(x) (x == ' ' || x == '\t' || x == '\r' || x == '\n')
static const char space[] = " \t\r\n";
static void dns_set_serv_internal(struct dns_ctx *ctx, char *serv) {
dns_add_serv(ctx, NULL);
for(serv = strtok(serv, space); serv; serv = strtok(NULL, space))
dns_add_serv(ctx, serv);
}
static void dns_set_srch_internal(struct dns_ctx *ctx, char *srch) {
dns_add_srch(ctx, NULL);
for(srch = strtok(srch, space); srch; srch = strtok(NULL, space))
dns_add_srch(ctx, srch);
}
#ifdef WINDOWS
#ifndef NO_IPHLPAPI
/* Apparently, some systems does not have proper headers for IPHLPAIP to work.
* The best is to upgrade headers, but here's another, ugly workaround for
* this: compile with -DNO_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; pAddr = pAddr->Next)
for (pDnsAddr = pAddr->FirstDnsServerAddress;
pDnsAddr;
pDnsAddr = pDnsAddr->Next)
dns_add_serv_s(ctx, pDnsAddr->Address.lpSockaddr);
ret = 0;
freemem:
free(pAddrBuf);
freelib:
FreeLibrary(h_iphlpapi);
return ret;
}
#else /* NO_IPHLPAPI */
#define dns_initns_iphlpapi(ctx) (-1)
#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, (BYTE*)valBuf, &len);
if (res != ERROR_SUCCESS || !len || !valBuf[0]) {
len = sizeof(valBuf) - 1;
res = RegQueryValueEx(hk, "DhcpNameServer", NULL, &type,
(BYTE*)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;
}
#else /* !WINDOWS */
static int dns_init_resolvconf(struct dns_ctx *ctx) {
char *v;
char buf[2049]; /* this buffer is used to hold /etc/resolv.conf */
int has_srch = 0;
/* 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));
has_srch = 1;
}
else if (strcmp(line, "search") == 0) {
dns_set_srch_internal(ctx, v);
has_srch = 1;
}
else if (strcmp(line, "nameserver") == 0)
dns_add_serv(ctx, strtok(v, space));
else if (strcmp(line, "options") == 0)
dns_set_opts(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);
has_srch = 1;
}
if ((v = getenv("RES_OPTIONS")) != NULL)
dns_set_opts(ctx, v);
/* if still no search list, use local domain name */
if (has_srch &&
gethostname(buf, sizeof(buf) - 1) == 0 &&
(v = strchr(buf, '.')) != NULL &&
*++v != '\0')
dns_add_srch(ctx, v);
return 0;
}
#endif /* !WINDOWS */
int dns_init(struct dns_ctx *ctx, int do_open) {
if (!ctx)
ctx = &dns_defctx;
dns_reset(ctx);
#ifdef WINDOWS
if (dns_initns_iphlpapi(ctx) != 0)
dns_initns_registry(ctx);
/*XXX WINDOWS: probably good to get default domain and search list too...
* And options. Something is in registry. */
/*XXX WINDOWS: maybe environment variables are also useful? */
#else
dns_init_resolvconf(ctx);
#endif
return do_open ? dns_open(ctx) : 0;
}

67
deps/udns/udns_misc.c

@ -0,0 +1,67 @@
/* $Id: udns_misc.c,v 1.8 2005/04/05 22:51:32 mjt Exp $
miscellaneous routines
Copyright (C) 2005 Michael Tokarev <mjt@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;
}

169
deps/udns/udns_parse.c

@ -0,0 +1,169 @@
/* $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@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;
}

1294
deps/udns/udns_resolver.c

File diff suppressed because it is too large

123
deps/udns/udns_rr_a.c

@ -0,0 +1,123 @@
/* $Id: udns_rr_a.c,v 1.16 2007/01/09 04:44:51 mjt Exp $
parse/query A/AAAA IN records
Copyright (C) 2005 Michael Tokarev <mjt@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>
#ifndef WINDOWS
# 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) {
#ifdef AF_INET
assert(sizeof(struct in_addr) == 4);
#endif
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);
}

91
deps/udns/udns_rr_mx.c

@ -0,0 +1,91 @@
/* $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@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);
}

128
deps/udns/udns_rr_naptr.c

@ -0,0 +1,128 @@
/* $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@corpit.ru>
Copyright (C) 2006 Mikael Magnusson <mikma@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);
}

109
deps/udns/udns_rr_ptr.c

@ -0,0 +1,109 @@
/* $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@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));
}

154
deps/udns/udns_rr_srv.c

@ -0,0 +1,154 @@
/* $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@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@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);
}

98
deps/udns/udns_rr_txt.c

@ -0,0 +1,98 @@
/* $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@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);
}

302
src/dns.cc

@ -0,0 +1,302 @@
#include "node.h"
#include "dns.h"
#include "events.h"
#include <stdlib.h> /* exit() */
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <v8.h>
#include <ev.h>
#include <udns.h>
using namespace v8;
using namespace node;
static ev_io io_watcher;
static ev_timer timer_watcher;
static inline void
set_timeout ()
{
int maxwait = 20;
int wait = dns_timeouts(NULL, maxwait, ev_now(EV_DEFAULT_UC));
ev_timer_stop(EV_DEFAULT_UC_ &timer_watcher);
if (!dns_active(NULL)) {
ev_timer_stop(EV_DEFAULT_UC_ &timer_watcher);
return;
}
if (wait >= 0) {
ev_timer_set(&timer_watcher, (double)wait, 0.0);
ev_timer_start(EV_DEFAULT_UC_ &timer_watcher);
}
}
static inline void
maybe_start ()
{
ev_io_start(EV_DEFAULT_UC_ &io_watcher);
set_timeout();
}
static void
ioevent (EV_P_ ev_io *_watcher, int revents)
{
assert(revents == EV_READ);
assert(_watcher == &io_watcher);
dns_ioevent(NULL, ev_now(EV_DEFAULT_UC));
if (!dns_active(NULL)) ev_io_stop(EV_DEFAULT_UC_ &io_watcher);
set_timeout();
}
static void
timeout (EV_P_ ev_timer *_watcher, int revents)
{
assert(revents == EV_TIMEOUT);
assert(_watcher == &timer_watcher);
set_timeout();
}
static void
ResolveError (Promise *promise)
{
HandleScope scope;
int status = dns_status(NULL);
assert(status < 0);
Local<String> msg = String::New(dns_strerror(status));
Local<Value> argv[2] = { Integer::New(status), msg };
promise->EmitError(2, argv);
}
static void
AfterResolveA4 (struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data)
{
assert(ctx == &dns_defctx);
HandleScope scope;
Promise *promise = reinterpret_cast<Promise*>(data);
assert(promise);
if (result == NULL) {
ResolveError(promise);
return;
}
/* canonical name */
Local<String> cname = String::New(result->dnsa4_cname);
/* Time-To-Live (TTL) value */
Local<Integer> ttl = Integer::New(result->dnsa4_ttl);
Local<Array> addresses = Array::New(result->dnsa4_nrr);
for (int i = 0; i < result->dnsa4_nrr; i++) {
HandleScope loop_scope;
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(result->dnsa4_addr[i]), ip, INET_ADDRSTRLEN);
Local<String> address = String::New(ip);
addresses->Set(Integer::New(i), address);
}
Local<Value> argv[3] = { addresses, ttl, cname };
promise->EmitSuccess(3, argv);
}
static void
AfterResolveA6 (struct dns_ctx *ctx, struct dns_rr_a6 *result, void *data)
{
assert(ctx == &dns_defctx);
HandleScope scope;
Promise *promise = reinterpret_cast<Promise*>(data);
assert(promise);
if (result == NULL) {
ResolveError(promise);
return;
}
/* canonical name */
Local<String> cname = String::New(result->dnsa6_cname);
/* Time-To-Live (TTL) value */
Local<Integer> ttl = Integer::New(result->dnsa6_ttl);
Local<Array> addresses = Array::New(result->dnsa6_nrr);
for (int i = 0; i < result->dnsa6_nrr; i++) {
HandleScope loop_scope;
char ip[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &(result->dnsa6_addr[i]), ip, INET6_ADDRSTRLEN);
Local<String> address = String::New(ip);
addresses->Set(Integer::New(i), address);
}
Local<Value> argv[3] = { addresses, ttl, cname };
promise->EmitSuccess(3, argv);
}
static Handle<Value>
ResolveA (int type, const Arguments& args)
{
HandleScope scope;
if (args.Length() == 0 || !args[0]->IsString()) {
return ThrowException(String::New("Argument must be a string."));
}
String::Utf8Value name(args[0]->ToString());
Promise *promise = Promise::Create();
struct dns_query *query;
switch (type) {
case DNS_T_A:
query = dns_submit_a4(NULL, *name, 0, AfterResolveA4, promise);
break;
case DNS_T_AAAA:
query = dns_submit_a6(NULL, *name, 0, AfterResolveA6, promise);
break;
default:
return ThrowException(String::New("Unsupported type"));
}
assert(query); // TODO better error handling.
maybe_start();
return scope.Close(promise->Handle());
}
static Handle<Value>
ResolveA4 (const Arguments& args)
{
return ResolveA(DNS_T_A, args);
}
static Handle<Value>
ResolveA6 (const Arguments& args)
{
return ResolveA(DNS_T_AAAA, args);
}
static void
AfterReverse (struct dns_ctx *ctx, struct dns_rr_ptr *result, void *data)
{
assert(ctx == &dns_defctx);
HandleScope scope;
Promise *promise = reinterpret_cast<Promise*>(data);
assert(promise);
if (result == NULL) {
ResolveError(promise);
return;
}
/* canonical name */
Local<String> cname = String::New(result->dnsptr_cname);
/* Time-To-Live (TTL) value */
Local<Integer> ttl = Integer::New(result->dnsptr_ttl);
Local<Array> domains = Array::New();
for (int i = 0; i < result->dnsptr_nrr; i++) {
HandleScope loop_scope;
Local<String> domain = String::New(result->dnsptr_ptr[i]);
domains->Set(Integer::New(i), domain);
}
Local<Value> argv[3] = { domains, ttl, cname };
promise->EmitSuccess(3, argv);
}
static Handle<Value>
Reverse (const Arguments& args)
{
HandleScope scope;
if (args.Length() == 0 || !args[0]->IsString()) {
return ThrowException(String::New("Argument must be a string."));
}
String::Utf8Value ip_address(args[0]->ToString());
union {
struct in_addr addr;
struct in6_addr addr6;
} a;
bool v4;
if (dns_pton(AF_INET, *ip_address, &a.addr) > 0) {
v4 = true;
} else if (dns_pton(AF_INET6, *ip_address, &a.addr6) > 0) {
v4 = false;
} else {
return ThrowException(String::New("Invalid IP address"));
}
Promise *promise = Promise::Create();
struct dns_query *query;
if (v4) {
query = dns_submit_a4ptr(NULL, &a.addr, AfterReverse, promise);
} else {
query = dns_submit_a6ptr(NULL, &a.addr6, AfterReverse, promise);
}
assert(query); // TODO better error handling.
maybe_start();
return scope.Close(promise->Handle());
}
void
DNS::Initialize (Handle<Object> target)
{
if (dns_init(NULL, 0) < 0) {
fprintf(stderr, "Error initializing UDNS context\n");
exit(-2);
}
int fd = dns_open(NULL);
ev_io_init(&io_watcher, ioevent, fd, EV_READ);
ev_init(&timer_watcher, timeout);
HandleScope scope;
target->Set(String::NewSymbol("TEMPFAIL"), Integer::New(DNS_E_TEMPFAIL));
target->Set(String::NewSymbol("PROTOCOL"), Integer::New(DNS_E_PROTOCOL));
target->Set(String::NewSymbol("NXDOMAIN"), Integer::New(DNS_E_NXDOMAIN));
target->Set(String::NewSymbol("NODATA"), Integer::New(DNS_E_NODATA));
target->Set(String::NewSymbol("NOMEM"), Integer::New(DNS_E_NOMEM));
target->Set(String::NewSymbol("BADQUERY"), Integer::New(DNS_E_BADQUERY));
Local<FunctionTemplate> resolve4 = FunctionTemplate::New(ResolveA4);
target->Set(String::NewSymbol("resolve4"), resolve4->GetFunction());
Local<FunctionTemplate> resolve6 = FunctionTemplate::New(ResolveA6);
target->Set(String::NewSymbol("resolve6"), resolve6->GetFunction());
Local<FunctionTemplate> reverse = FunctionTemplate::New(Reverse);
target->Set(String::NewSymbol("reverse"), reverse->GetFunction());
}

14
src/dns.h

@ -0,0 +1,14 @@
#ifndef node_dns_h
#define node_dns_h
#include <v8.h>
namespace node {
class DNS {
public:
static void Initialize(v8::Handle<v8::Object> target);
};
} // namespace node
#endif // node_dns_h

33
src/events.cc

@ -131,7 +131,6 @@ Promise::Create (void)
promise->Wrap(handle); promise->Wrap(handle);
promise->Attach(); promise->Attach();
ev_ref(EV_DEFAULT_UC);
return promise; return promise;
} }
@ -142,7 +141,6 @@ Promise::EmitSuccess (int argc, v8::Handle<v8::Value> argv[])
bool r = Emit("success", argc, argv); bool r = Emit("success", argc, argv);
Detach(); Detach();
ev_unref(EV_DEFAULT_UC);
return r; return r;
} }
@ -153,7 +151,36 @@ Promise::EmitError (int argc, v8::Handle<v8::Value> argv[])
bool r = Emit("error", argc, argv); bool r = Emit("error", argc, argv);
Detach(); Detach();
ev_unref(EV_DEFAULT_UC);
return r; return r;
} }
void
EIOPromise::Attach (void)
{
ObjectWrap::Attach();
ev_ref(EV_DEFAULT_UC);
}
void
EIOPromise::Detach (void)
{
ObjectWrap::Detach();
ev_unref(EV_DEFAULT_UC);
}
EIOPromise*
EIOPromise::Create (void)
{
HandleScope scope;
Local<Object> handle =
Promise::constructor_template->GetFunction()->NewInstance();
EIOPromise *promise = new EIOPromise();
promise->Wrap(handle);
promise->Attach();
return promise;
}

11
src/events.h

@ -36,5 +36,16 @@ class Promise : public EventEmitter {
Promise () : EventEmitter() { } Promise () : EventEmitter() { }
}; };
class EIOPromise : public Promise {
public:
static EIOPromise* Create (void);
protected:
void Attach (void);
void Detach (void);
EIOPromise () : Promise() { }
};
} // namespace node } // namespace node
#endif #endif

34
src/file.cc

@ -31,7 +31,7 @@ using namespace node;
static int static int
AfterClose (eio_req *req) AfterClose (eio_req *req)
{ {
Promise *promise = reinterpret_cast<Promise*>(req->data); EIOPromise *promise = reinterpret_cast<EIOPromise*>(req->data);
if (req->result == 0) { if (req->result == 0) {
promise->EmitSuccess(0, NULL); promise->EmitSuccess(0, NULL);
} else { } else {
@ -48,7 +48,7 @@ Close (const Arguments& args)
HandleScope scope; HandleScope scope;
int fd = args[0]->Int32Value(); int fd = args[0]->Int32Value();
Promise *promise = Promise::Create(); EIOPromise *promise = EIOPromise::Create();
eio_close(fd, EIO_PRI_DEFAULT, AfterClose, promise); eio_close(fd, EIO_PRI_DEFAULT, AfterClose, promise);
return scope.Close(promise->Handle()); return scope.Close(promise->Handle());
@ -57,7 +57,7 @@ Close (const Arguments& args)
static int static int
AfterRename (eio_req *req) AfterRename (eio_req *req)
{ {
Promise *promise = reinterpret_cast<Promise*>(req->data); EIOPromise *promise = reinterpret_cast<EIOPromise*>(req->data);
if (req->result == 0) { if (req->result == 0) {
promise->EmitSuccess(0, NULL); promise->EmitSuccess(0, NULL);
} else { } else {
@ -74,7 +74,7 @@ static Handle<Value> Rename (const Arguments& args)
String::Utf8Value path(args[0]->ToString()); String::Utf8Value path(args[0]->ToString());
String::Utf8Value new_path(args[1]->ToString()); String::Utf8Value new_path(args[1]->ToString());
Promise *promise = Promise::Create(); EIOPromise *promise = EIOPromise::Create();
eio_rename(*path, *new_path, EIO_PRI_DEFAULT, AfterRename, promise); eio_rename(*path, *new_path, EIO_PRI_DEFAULT, AfterRename, promise);
return scope.Close(promise->Handle()); return scope.Close(promise->Handle());
@ -83,7 +83,7 @@ static Handle<Value> Rename (const Arguments& args)
static int static int
AfterUnlink (eio_req *req) AfterUnlink (eio_req *req)
{ {
Promise *promise = reinterpret_cast<Promise*>(req->data); EIOPromise *promise = reinterpret_cast<EIOPromise*>(req->data);
if (req->result == 0) { if (req->result == 0) {
promise->EmitSuccess(0, NULL); promise->EmitSuccess(0, NULL);
} else { } else {
@ -98,7 +98,7 @@ static Handle<Value> Unlink (const Arguments& args)
return ThrowException(BAD_ARGUMENTS); return ThrowException(BAD_ARGUMENTS);
HandleScope scope; HandleScope scope;
String::Utf8Value path(args[0]->ToString()); String::Utf8Value path(args[0]->ToString());
Promise *promise = Promise::Create(); EIOPromise *promise = EIOPromise::Create();
eio_unlink(*path, EIO_PRI_DEFAULT, AfterUnlink, promise); eio_unlink(*path, EIO_PRI_DEFAULT, AfterUnlink, promise);
return scope.Close(promise->Handle()); return scope.Close(promise->Handle());
} }
@ -106,7 +106,7 @@ static Handle<Value> Unlink (const Arguments& args)
static int static int
AfterRMDir (eio_req *req) AfterRMDir (eio_req *req)
{ {
Promise *promise = reinterpret_cast<Promise*>(req->data); EIOPromise *promise = reinterpret_cast<EIOPromise*>(req->data);
if (req->result == 0) { if (req->result == 0) {
promise->EmitSuccess(0, NULL); promise->EmitSuccess(0, NULL);
} else { } else {
@ -121,7 +121,7 @@ static Handle<Value> RMDir (const Arguments& args)
return ThrowException(BAD_ARGUMENTS); return ThrowException(BAD_ARGUMENTS);
HandleScope scope; HandleScope scope;
String::Utf8Value path(args[0]->ToString()); String::Utf8Value path(args[0]->ToString());
Promise *promise = Promise::Create(); EIOPromise *promise = EIOPromise::Create();
eio_rmdir(*path, EIO_PRI_DEFAULT, AfterRMDir, promise); eio_rmdir(*path, EIO_PRI_DEFAULT, AfterRMDir, promise);
return scope.Close(promise->Handle()); return scope.Close(promise->Handle());
} }
@ -129,7 +129,7 @@ static Handle<Value> RMDir (const Arguments& args)
static int static int
AfterOpen (eio_req *req) AfterOpen (eio_req *req)
{ {
Promise *promise = reinterpret_cast<Promise*>(req->data); EIOPromise *promise = reinterpret_cast<EIOPromise*>(req->data);
if (req->result < 0) { if (req->result < 0) {
promise->EmitError(0, NULL); promise->EmitError(0, NULL);
@ -156,7 +156,7 @@ Open (const Arguments& args)
int flags = args[1]->Int32Value(); int flags = args[1]->Int32Value();
mode_t mode = static_cast<mode_t>(args[2]->Int32Value()); mode_t mode = static_cast<mode_t>(args[2]->Int32Value());
Promise *promise = Promise::Create(); EIOPromise *promise = EIOPromise::Create();
eio_open(*path, flags, mode, EIO_PRI_DEFAULT, AfterOpen, promise); eio_open(*path, flags, mode, EIO_PRI_DEFAULT, AfterOpen, promise);
return scope.Close(promise->Handle()); return scope.Close(promise->Handle());
@ -165,7 +165,7 @@ Open (const Arguments& args)
static int static int
AfterWrite (eio_req *req) AfterWrite (eio_req *req)
{ {
Promise *promise = reinterpret_cast<Promise*>(req->data); EIOPromise *promise = reinterpret_cast<EIOPromise*>(req->data);
if (req->result < 0) { if (req->result < 0) {
promise->EmitError(0, NULL); promise->EmitError(0, NULL);
@ -231,7 +231,7 @@ Write (const Arguments& args)
return ThrowException(BAD_ARGUMENTS); return ThrowException(BAD_ARGUMENTS);
} }
Promise *promise = Promise::Create(); EIOPromise *promise = EIOPromise::Create();
eio_write(fd, buf, len, pos, EIO_PRI_DEFAULT, AfterWrite, promise); eio_write(fd, buf, len, pos, EIO_PRI_DEFAULT, AfterWrite, promise);
return scope.Close(promise->Handle()); return scope.Close(promise->Handle());
} }
@ -239,7 +239,7 @@ Write (const Arguments& args)
static int static int
AfterUtf8Read (eio_req *req) AfterUtf8Read (eio_req *req)
{ {
Promise *promise = reinterpret_cast<Promise*>(req->data); EIOPromise *promise = reinterpret_cast<EIOPromise*>(req->data);
if (req->result < 0) { if (req->result < 0) {
promise->EmitError(0, NULL); promise->EmitError(0, NULL);
@ -267,7 +267,7 @@ AfterUtf8Read (eio_req *req)
static int static int
AfterRawRead(eio_req *req) AfterRawRead(eio_req *req)
{ {
Promise *promise = reinterpret_cast<Promise*>(req->data); EIOPromise *promise = reinterpret_cast<EIOPromise*>(req->data);
if (req->result < 0) { if (req->result < 0) {
promise->EmitError(0, NULL); promise->EmitError(0, NULL);
@ -325,7 +325,7 @@ Read (const Arguments& args)
encoding = static_cast<enum encoding>(args[3]->Int32Value()); encoding = static_cast<enum encoding>(args[3]->Int32Value());
} }
Promise *promise = Promise::Create(); EIOPromise *promise = EIOPromise::Create();
// NOTE: 2nd param: NULL pointer tells eio to allocate it itself // NOTE: 2nd param: NULL pointer tells eio to allocate it itself
eio_read(fd, NULL, len, pos, EIO_PRI_DEFAULT, eio_read(fd, NULL, len, pos, EIO_PRI_DEFAULT,
@ -337,7 +337,7 @@ Read (const Arguments& args)
static int static int
AfterStat (eio_req *req) AfterStat (eio_req *req)
{ {
Promise *promise = reinterpret_cast<Promise*>(req->data); EIOPromise *promise = reinterpret_cast<EIOPromise*>(req->data);
if (req->result < 0) { if (req->result < 0) {
promise->EmitError(0, NULL); promise->EmitError(0, NULL);
@ -393,7 +393,7 @@ Stat (const Arguments& args)
String::Utf8Value path(args[0]->ToString()); String::Utf8Value path(args[0]->ToString());
Promise *promise = Promise::Create(); EIOPromise *promise = EIOPromise::Create();
eio_stat(*path, EIO_PRI_DEFAULT, AfterStat, promise); eio_stat(*path, EIO_PRI_DEFAULT, AfterStat, promise);

5
src/node.cc

@ -1,6 +1,7 @@
#include "node.h" #include "node.h"
#include "events.h" #include "events.h"
#include "dns.h"
#include "net.h" #include "net.h"
#include "file.h" #include "file.h"
#include "http.h" #include "http.h"
@ -247,6 +248,10 @@ Load (int argc, char *argv[])
DefineConstants(node_obj); DefineConstants(node_obj);
Local<Object> dns = Object::New();
node_obj->Set(String::NewSymbol("dns"), dns);
DNS::Initialize(dns);
Local<Object> fs = Object::New(); Local<Object> fs = Object::New();
node_obj->Set(String::NewSymbol("fs"), fs); node_obj->Set(String::NewSymbol("fs"), fs);
File::Initialize(fs); File::Initialize(fs);

4
src/object_wrap.h

@ -50,7 +50,7 @@ class ObjectWrap {
* Attached objects will not be garbage collected, even if * Attached objects will not be garbage collected, even if
* all references are lost. * all references are lost.
*/ */
void Attach() { virtual void Attach() {
assert(!handle_.IsEmpty()); assert(!handle_.IsEmpty());
assert(handle_.IsWeak()); assert(handle_.IsWeak());
attached_++; attached_++;
@ -65,7 +65,7 @@ class ObjectWrap {
* *
* DO NOT CALL THIS FROM DESTRUCTOR * DO NOT CALL THIS FROM DESTRUCTOR
*/ */
void Detach() { virtual void Detach() {
assert(!handle_.IsEmpty()); assert(!handle_.IsEmpty());
assert(handle_.IsWeak()); assert(handle_.IsWeak());
assert(attached_ > 0); assert(attached_ > 0);

26
test/mjsunit/disabled/test_dns.js

@ -0,0 +1,26 @@
for (var i = 2; i < ARGV.length; i++) {
var name = ARGV[i]
puts("looking up " + name);
var resolution = node.dns.resolve4(name);
resolution.addCallback(function (addresses, ttl, cname) {
puts("addresses: " + JSON.stringify(addresses));
puts("ttl: " + JSON.stringify(ttl));
puts("cname: " + JSON.stringify(cname));
for (var i = 0; i < addresses.length; i++) {
var a = addresses[i];
var reversing = node.dns.reverse(a);
reversing.addCallback( function (domains, ttl, cname) {
puts("reverse for " + a + ": " + JSON.stringify(domains));
});
reversing.addErrback( function (code, msg) {
puts("reverse for " + a + " failed: " + msg);
});
}
});
resolution.addErrback(function (code, msg) {
puts("error: " + msg);
});
}

69
website/api.txt

@ -1008,6 +1008,75 @@ necessary in case of errors (parse error or so).
=== DNS
Here is an example of which reads domains from the command line, resolves
them, then reverse resolves the IP addresses returned.
-------------------------------------------------------------------------
for (var i = 2; i < ARGV.length; i++) {
var name = ARGV[i]
puts("looking up " + name);
var resolution = node.dns.resolve4(name);
resolution.addCallback(function (addresses, ttl, cname) {
puts("addresses: " + JSON.stringify(addresses));
puts("ttl: " + JSON.stringify(ttl));
puts("cname: " + JSON.stringify(cname));
for (var i = 0; i < addresses.length; i++) {
var a = addresses[i];
var reversing = node.dns.reverse(a);
reversing.addCallback( function (domains, ttl, cname) {
puts("reverse for " + a + ": " + JSON.stringify(domains));
});
reversing.addErrback( function (code, msg) {
puts("reverse for " + a + " failed: " + msg);
});
}
});
resolution.addErrback(function (code, msg) {
puts("error: " + msg);
});
}
-------------------------------------------------------------------------
+node.dns.resolve4(domain)+::
Resolves a domain (e.g. +"google.com"+) into an array of IPv4 addresses (e.g.
+["74.125.79.104","74.125.79.105","74.125.79.106","74.125.79.147","74.125.79.99","74.125.79.103"]+).
This function returns a promise.
- on success: returns +addresses, ttl, cname+. +ttl+ (time-to-live) is an integer
specifying the number of seconds this result is valid for. +cname+ is the
canonical name for the query.
- on error: returns +code, msg+. +code+ is one of the error codes listed
below and +msg+ is a string describing the error in English.
+node.dns.resolve6(domain)+::
The same as +node.dns.resolve4()+ except for IPv6 queries (an +AAAA+ query).
+node.dns.reverse(ip)+::
Reverse resolves an ip address to an array of domain names.
- on success: returns +domains, ttl, cname+. +ttl+ (time-to-live) is an integer
specifying the number of seconds this result is valid for. +cname+ is the
canonical name for the query. +domains+ is an array of domains.
- on error: returns +code, msg+. +code+ is one of the error codes listed
below and +msg+ is a string describing the error in English.
Each DNS query can return an error code.
- +node.dns.TEMPFAIL+: timeout, SERVFAIL or similar.
- +node.dns.PROTOCOL+: got garbled reply.
- +node.dns.NXDOMAIN+: domain does not exists.
- +node.dns.NODATA+: domain exists but no data of reqd type.
- +node.dns.NOMEM+: out of memory while processing.
- +node.dns.BADQUERY+: the query is malformed.
// vim: set syntax=asciidoc: // vim: set syntax=asciidoc:

83
wscript

@ -1,7 +1,6 @@
# /usr/bin/env python # /usr/bin/env python
import Options import Options
import sys import sys, os, shutil
import os
from os.path import join, dirname, abspath from os.path import join, dirname, abspath
from logging import fatal from logging import fatal
@ -31,6 +30,29 @@ def set_options(opt):
, dest='efence' , dest='efence'
) )
def mkdir_p(dir):
if not os.path.exists (dir):
os.makedirs (dir)
def conf_subproject (conf, subdir, command=None):
print("---- %s ----" % subdir)
src = join(conf.srcdir, subdir)
if not os.path.exists (src): fatal("no such subproject " + subdir)
default_tgt = join(conf.blddir, "default", subdir)
if not os.path.exists(default_tgt):
shutil.copytree(src, default_tgt)
if command:
if os.system("cd %s && %s" % (default_tgt, command)) != 0:
fatal("Configuring %s failed." % (subdir))
debug_tgt = join(conf.blddir, "debug", subdir)
if not os.path.exists(debug_tgt):
shutil.copytree(default_tgt, debug_tgt)
def configure(conf): def configure(conf):
conf.check_tool('compiler_cxx') conf.check_tool('compiler_cxx')
conf.check_tool('compiler_cc') conf.check_tool('compiler_cc')
@ -50,6 +72,9 @@ def configure(conf):
conf.sub_config('deps/libeio') conf.sub_config('deps/libeio')
conf.sub_config('deps/libev') conf.sub_config('deps/libev')
conf_subproject(conf, 'deps/udns', './configure')
conf_subproject(conf, 'deps/v8')
# Not using TLS yet # Not using TLS yet
# if conf.check_cfg(package='gnutls', args='--cflags --libs', uselib_store="GNUTLS"): # if conf.check_cfg(package='gnutls', args='--cflags --libs', uselib_store="GNUTLS"):
# conf.define("HAVE_GNUTLS", 1) # conf.define("HAVE_GNUTLS", 1)
@ -75,30 +100,58 @@ def configure(conf):
conf.env.append_value('CXXFLAGS', ['-DNDEBUG', '-O3', '-m32']) conf.env.append_value('CXXFLAGS', ['-DNDEBUG', '-O3', '-m32'])
conf.write_config_header("config.h") conf.write_config_header("config.h")
def build(bld): def build_udns(bld):
bld.add_subdirs('deps/libeio deps/libev') default_build_dir = bld.srcnode.abspath(bld.env_of_name("default"))
default_dir = join(default_build_dir, "deps/udns")
static_lib = bld.env["staticlib_PATTERN"] % "udns"
### v8 rule = 'cd %s && make'
default = bld.new_task_gen(
target= join("deps/udns", static_lib),
rule= rule % default_dir,
before= "cxx",
install_path= None
)
bld.env["CPPPATH_UDNS"] = "deps/udns"
bld.env["STATICLIB_UDNS"] = "udns"
bld.env_of_name('default')["STATICLIB_UDNS"] = "udns"
bld.env_of_name('default')["LIBPATH_UDNS"] = default_dir
if bld.env["USE_DEBUG"]:
debug_build_dir = bld.srcnode.abspath(bld.env_of_name("debug"))
debug_dir = join(debug_build_dir, "deps/udns")
debug = default.clone("debug")
debug.rule = rule % debug_dir
#debug.target = join(debug_dir, static_lib)
bld.env_of_name('debug')["STATICLIB_UDNS"] = "udns"
bld.env_of_name('debug')["LIBPATH_UDNS"] = debug_dir
def build_v8(bld):
deps_src = join(bld.path.abspath(),"deps") deps_src = join(bld.path.abspath(),"deps")
deps_tgt = join(bld.srcnode.abspath(bld.env_of_name("default")),"deps") deps_tgt = join(bld.srcnode.abspath(bld.env_of_name("default")),"deps")
v8dir_src = join(deps_src,"v8") v8dir_src = join(deps_src,"v8")
v8dir_tgt = join(deps_tgt, "v8") v8dir_tgt = join(deps_tgt, "v8")
scons = os.path.join(cwd, 'tools/scons/scons.py') scons = os.path.join(cwd, 'tools/scons/scons.py')
v8rule = 'cp -rf %s %s && ' \ v8rule = 'cd %s && ' \
'cd %s && ' \
'python %s -Q mode=%s library=static snapshot=on' 'python %s -Q mode=%s library=static snapshot=on'
v8 = bld.new_task_gen( v8 = bld.new_task_gen(
target = join("deps/v8", bld.env["staticlib_PATTERN"] % "v8"), target = join("deps/v8", bld.env["staticlib_PATTERN"] % "v8"),
rule=v8rule % ( v8dir_src , deps_tgt , v8dir_tgt, scons, "release"), rule=v8rule % (v8dir_tgt, scons, "release"),
before="cxx", before="cxx",
install_path = None install_path = None
) )
bld.env["CPPPATH_V8"] = "deps/v8/include" bld.env["CPPPATH_V8"] = "deps/v8/include"
bld.env["LINKFLAGS_V8"] = ["-pthread", "-m32"]
bld.env_of_name('default')["STATICLIB_V8"] = "v8" bld.env_of_name('default')["STATICLIB_V8"] = "v8"
bld.env_of_name('default')["LIBPATH_V8"] = v8dir_tgt bld.env_of_name('default')["LIBPATH_V8"] = v8dir_tgt
bld.env_of_name('default')["LINKFLAGS_V8"] = ["-pthread", "-m32"]
### v8 debug ### v8 debug
if bld.env["USE_DEBUG"]: if bld.env["USE_DEBUG"]:
@ -109,9 +162,15 @@ def build(bld):
bld.env_of_name('debug')["STATICLIB_V8"] = "v8_g" bld.env_of_name('debug')["STATICLIB_V8"] = "v8_g"
bld.env_of_name('debug')["LIBPATH_V8"] = v8dir_tgt bld.env_of_name('debug')["LIBPATH_V8"] = v8dir_tgt
bld.env_of_name('debug')["LINKFLAGS_V8"] = ["-pthread", "-m32"] bld.env_of_name('debug')["LINKFLAGS_V8"] = ["-pthread", "-m32"]
v8_debug.rule = v8rule % ( v8dir_src , deps_tgt , v8dir_tgt, scons, "debug") v8_debug.rule = v8rule % (v8dir_tgt, scons, "debug")
v8_debug.target = join("deps/v8", bld.env["staticlib_PATTERN"] % "v8_g") v8_debug.target = join("deps/v8", bld.env["staticlib_PATTERN"] % "v8_g")
def build(bld):
bld.add_subdirs('deps/libeio deps/libev')
build_udns(bld)
build_v8(bld)
### evcom ### evcom
evcom = bld.new_task_gen("cc", "staticlib") evcom = bld.new_task_gen("cc", "staticlib")
evcom.source = "deps/evcom/evcom.c" evcom.source = "deps/evcom/evcom.c"
@ -164,6 +223,7 @@ def build(bld):
src/events.cc src/events.cc
src/http.cc src/http.cc
src/net.cc src/net.cc
src/dns.cc
src/file.cc src/file.cc
src/timer.cc src/timer.cc
src/process.cc src/process.cc
@ -173,12 +233,13 @@ def build(bld):
src/ src/
deps/v8/include deps/v8/include
deps/libev deps/libev
deps/udns
deps/libeio deps/libeio
deps/evcom deps/evcom
deps/http_parser deps/http_parser
""" """
node.uselib_local = "evcom ev eio http_parser" node.uselib_local = "evcom ev eio http_parser"
node.uselib = "V8 EXECINFO PROFILER EFENCE" node.uselib = "UDNS V8 EXECINFO PROFILER EFENCE"
node.install_path = '${PREFIX}/bin' node.install_path = '${PREFIX}/bin'
node.chmod = 0755 node.chmod = 0755

Loading…
Cancel
Save