r2991 - in udns: branches/upstream/trunk branches/upstream/trunk/debian tags/upstream tags/upstream/0.0.9pre tags/upstream/0.0.9pre/debian

mikma at minisip.org mikma at minisip.org
Wed Dec 6 13:57:22 CET 2006


Author: mikma
Date: 2006-12-06 13:57:21 +0100 (Wed, 06 Dec 2006)
New Revision: 2991

Added:
   udns/branches/upstream/trunk/NOTES
   udns/branches/upstream/trunk/udns_rr_naptr.c
   udns/tags/upstream/0.0.9pre/
   udns/tags/upstream/0.0.9pre/NOTES
   udns/tags/upstream/0.0.9pre/udns_rr_naptr.c
Modified:
   udns/branches/upstream/trunk/Makefile
   udns/branches/upstream/trunk/TODO
   udns/branches/upstream/trunk/debian/changelog
   udns/branches/upstream/trunk/debian/rules
   udns/branches/upstream/trunk/dnsget.c
   udns/branches/upstream/trunk/udns.3
   udns/branches/upstream/trunk/udns.h
   udns/branches/upstream/trunk/udns_dn.c
   udns/branches/upstream/trunk/udns_resolver.c
   udns/branches/upstream/trunk/udns_rr_txt.c
   udns/tags/upstream/0.0.9pre/Makefile
   udns/tags/upstream/0.0.9pre/TODO
   udns/tags/upstream/0.0.9pre/debian/changelog
   udns/tags/upstream/0.0.9pre/debian/rules
   udns/tags/upstream/0.0.9pre/dnsget.c
   udns/tags/upstream/0.0.9pre/udns.3
   udns/tags/upstream/0.0.9pre/udns.h
   udns/tags/upstream/0.0.9pre/udns_dn.c
   udns/tags/upstream/0.0.9pre/udns_resolver.c
   udns/tags/upstream/0.0.9pre/udns_rr_txt.c
Log:
Add udns upstream pre release 0.0.9pre


Modified: udns/branches/upstream/trunk/Makefile
===================================================================
--- udns/branches/upstream/trunk/Makefile	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/branches/upstream/trunk/Makefile	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,5 +1,5 @@
 #! /usr/bin/make -rf
-# $Id: Makefile,v 1.38 2005/09/12 12:09:10 mjt Exp $
+# $Id: Makefile,v 1.42 2006/11/29 21:27:01 mjt Exp $
 # libudns Makefile
 #
 # Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
@@ -20,13 +20,14 @@
 # write to the Free Software Foundation, Inc., 59 Temple Place,
 # Suite 330, Boston, MA  02111-1307  USA
 
-VERS   = 0.0.8
+VERS   = 0.0.9pre
 SRCS   = udns_dn.c udns_dntosp.c udns_parse.c udns_resolver.c udns_misc.c \
 	udns_rr_a.c udns_rr_ptr.c udns_rr_mx.c udns_rr_txt.c udns_bl.c \
-	udns_rr_srv.c udns_codes.c
+	udns_rr_srv.c udns_rr_naptr.c udns_codes.c
 USRCS  = dnsget.c rblcheck.c ex-rdns.c
+DEB    = debian/copyright debian/changelog debian/control debian/rules
 DIST   = COPYING.LGPL udns.h udns.3 dnsget.1 rblcheck.1 $(SRCS) $(USRCS) \
-	Makefile TODO
+	Makefile TODO NOTES
 
 OBJS   = $(SRCS:.c=.o) $(GEN:.c=.o)
 LIB    = libudns.a
@@ -114,9 +115,10 @@
 	mv $@.tmp $@
 
 dist: $(NAMEPFX).tar.gz
-$(NAMEPFX).tar.gz: $(DIST)
-	mkdir $(NAMEPFX)
+$(NAMEPFX).tar.gz: $(DIST) $(DEB)
+	mkdir $(NAMEPFX) $(NAMEPFX)/debian
 	ln $(DIST) $(NAMEPFX)
+	ln $(DEB) $(NAMEPFX)/debian
 	tar cvfz $@ $(NAMEPFX)
 	rm -rf $(NAMEPFX)
 subdist:

Added: udns/branches/upstream/trunk/NOTES
===================================================================
--- udns/branches/upstream/trunk/NOTES	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/branches/upstream/trunk/NOTES	2006-12-06 12:57:21 UTC (rev 2991)
@@ -0,0 +1,193 @@
+Assorted notes about udns (library).
+
+UDP-only mode
+~~~~~~~~~~~~~
+
+First of all, since udns is (currently) UDP-only, there are some
+shortcomings.
+
+It assumes that a reply will fit into a UDP buffer.  With adoption of EDNS0,
+and general robustness of IP stacks, in most cases it's not an issue.  But
+in some cases there may be problems:
+
+ - if an RRset is "very large" so it does not fit even in buffer of size
+   requested by the library (current default is 4096; some servers limits
+   it further), we will not see the reply, or will only see "damaged"
+   reply (depending on the server)
+
+ - many DNS servers ignores EDNS0 option requests.  In this case, no matter
+   which buffer size udns library will request, such servers reply is limited
+   to 512 bytes (standard pre-EDNS0 DNS packet size).
+
+ - some DNS servers, notable the ones used by Verisign for certain top-level
+   domains, chokes on EDNS0-enabled queries, returning FORMERR.  Such
+   behavior isn't prohibited by DNS standards, but in my opinion it's at
+   least weird - the server can easily ignore EDNS0 options and send a
+   reply, instead of sending error.
+   Currently, udns does nothing in this situation, completely ignoring the
+   error returned by the server, and continue waiting for reply.  It probably
+   should grok that this server does not understand EDNS0 and retry w/o the
+   options, but it does not.  The end result - esp. if your local DNS
+   server or - worse - broken firewall which inspects DNS packets and drops
+   the ones which - from its point of view - are "broken" - is that you
+   see only TEMPFAIL errors from the library trying to resolve ANY names.
+
+Implementing TCP mode (together with non-EDNS0 fall-back as above) isn't
+difficult, but it complicates API significantly.  Currently udns uses only
+single UDP socket (or - maybe in the future - two, see below), but in case of
+TCP, it will need to open and close sockets for TCP connections left and
+right, and that have to be integrated into an application's event loop in
+an easy and efficient way.  Plus all the timeouts - different for connect(),
+write, and several stages of read.
+
+IPv6 vs IPv4 usage
+~~~~~~~~~~~~~~~~~~
+
+This is only relevant for nameservers reachable over IPv6, NOT for IPv6
+queries.  I.e., if you've IPv6 addresses in 'nameservers' line in your
+/etc/resolv.conf file.  Even more: if you have BOTH IPv6 AND IPv4 addresses
+there.  Or pass them to udns initialization routines.
+
+Since udns uses a single UDP socket to communicate with all nameservers,
+it should support both v4 and v6 communications.  Most current platforms
+supports this mode - using PF_INET6 socket and V4MAPPED addresses, i.e,
+"tunnelling" IPv4 inside IPv6.  But not all systems supports this.  And
+more, it has been said that such mode is deprecated.
+
+So, list only IPv4 or only IPv6 addresses, but don't mix them, in your
+/etc/resolv.conf.
+
+An alternative is to use two sockets instead of 1 - one for IPv6 and one
+for IPv4.  For now I'm not sure if it's worth the complexity - again, of
+the API, not the library itself (but this will not simplify library either).
+
+Single socket for all queries
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Using single UDP socket for sending queries to all nameservers has obvious
+advantages.  First it's, again, trivial, simple to use API.  And simple
+library too.  Also, after sending queries to all nameservers (in case first
+didn't reply in time), we will be able to receive late reply from first
+nameserver and accept it.
+
+But this mode has disadvantages too.  Most important is that it's much easier
+to send fake reply to us, as the UDP port where we expects the reply to come
+to is constant during the whole lifetime of an application.  More secure
+implementations uses random port for every single query.  While port number
+(16 bits integer) can not hold much randomness, it's still of some help.
+Ok, udns is a stub resolver, so it expects sorta friendly environment, but
+on LAN it's usually much easier to fire an attack, due to the speed of local
+network, where a bad guy can generate alot of packets in a short time.
+
+Choosing of DNS QueryID
+~~~~~~~~~~~~~~~~~~~~~~~
+
+This is more a TODO item really.  Currently, udns uses sequential number for
+query IDs.  Which simplifies attacks even more (c.f. the previous item about
+single UDP port), making them nearly trivial.  The library should use random
+number for query ID.  But there's no portable way to get random numbers, even
+on various flavors of Unix.  It's possible to use low bits from tv_nsec field
+returned by gettimeofday() (current time, nanoseconds), but I wrote the library
+in a way to avoid making system calls where possible, because many syscalls
+means many context switches and slow processes as a result.  Maybe use some
+application-supplied callback to get random values will be a better way,
+defaulting to gettimeofday() method.
+
+Note that a single query - even if (re)sent to different nameservers, several
+times (due to no reply received in time), uses the same qID assigned when it
+was first dispatched.  So we have: single UDP socket (fixed port number),
+sequential (= trivially predictable) qIDs, and long lifetime of those qIDs.
+This all makes (local) attacks against the library really trivial.
+
+Assumptions about RRs returned
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Currently udns processes records in the reply it received sequentially.
+This means that order of the records is significant.  For example, if
+we asked for foo.bar A, but the server returned that foo.bar is a CNAME
+(alias) for bar.baz, and bar.baz, in turn, has address 1.2.3.4, when
+the CNAME should come first in reply, followed by A.  While DNS specs
+does not say anything about order of records - it's an rrSET - unordered, -
+I think an implementation which returns the records in "wrong" order is
+somewhat insane...  Well ok, to be fair, I don't really remember how
+udns handles this now - need to check this in source... ;)
+
+CNAME recursion
+~~~~~~~~~~~~~~~
+
+Another dark point of udns is the handling of CNAMEs returned as replies
+to non-CNAME queries.  If we asked for foo.bar A, but it's a CNAME, udns
+expects BOTH the CNAME itself and the target DN to be present in the reply.
+In other words, udns DOES NOT RECURSE CNAMES.  If we asked for foo.bar A,
+but only record in reply was that foo.bar is a CNAME for bar.baz, udns will
+return no records to an application (NXDOMAIN).  Strictly speaking, udns
+should repeat the query asking for bar.baz A, and recurse.  But since it's
+stub resolver, recursive resolver should recurse for us instead.
+
+It's not very difficult to implement, however.  Probably with some (global?)
+flag to en/dis-able the feature.  Provided there's some demand for it.
+
+To clarify: udns handles CNAME recursion in a single reply packet just fine.
+
+Error reporting
+~~~~~~~~~~~~~~~
+
+Too many places in the code (various failure paths) sets generic "TEMPFAIL"
+error condition.  For example, if no nameserver replied to our query, an
+application will get generic TEMPFAIL, instead of something like TIMEDOUT.
+This probably should be fixed, but most applications don't care about the
+exact reasons of failure - 4 common cases are already too much:
+  - query returned some valid data
+  - NXDOMAIN
+  - valid domain but no data of requested type - =NXDOMAIN in most cases
+  - temporary error - this one sometimes (incorrectly!) treated as NXDOMAIN
+    by (naive) applications.
+DNS isn't yes/no, it's at least 3 variants, temp err being the 3rd important
+case!  And adding more variations for the temp error case is complicating things
+even more - again, from an application writer standpoint.  For diagnostics,
+such more specific error cases are of good help.
+
+Planned API changes
+~~~~~~~~~~~~~~~~~~~
+
+At least one thing I want to change for 0.1 version is a way how queries are
+submitted.
+
+I want to made dns_query object to be owned by an application.  So that instead
+of udns library allocating it for the lifetime of query, it will be pre-
+allocated by an application.  This simplifies and enhances query submitting
+interface, and complicates it a bit too, in simplest cases.
+
+Currently, we have:
+
+dns_submit_dn(dn, cls, typ, flags, parse, cbck, data)
+dns_submit_p(name, cls, typ, flags, parse, cbck, data)
+dns_submit_a4(ctx, name, flags, cbck, data)
+
+and so on -- with many parameters missed for type-specific cases, but generic
+cases being too complex for most common usage.
+
+Instead, with dns_query being owned by an app, we will be able to separately
+set up various parts of the query - domain name (various forms), type&class,
+parser, flags, callback...  and even change them at runtime.  And we will also
+be able to reuse query structures, instead of allocating/freeing them every
+time.  So the whole thing will look something like:
+
+ q = dns_alloc_query();
+ dns_submit(dns_q_flags(dns_q_a4(q, name, cbck), DNS_F_NOSRCH), data);
+
+The idea is to have a set of functions accepting struct dns_query* and
+returning it (so the calls can be "nested" like the above), to set up
+relevant parts of the query - specific type of callback, conversion from
+(type-specific) query parameters into a domain name (this is for type-
+specific query initializers), and setting various flags and options and
+type&class things.
+
+One example where this is almost essential - if we want to support
+per-query set of nameservers (which isn't at all useless: imagine a
+high-volume mail server, were we want to direct DNSBL queries to a separate
+set of nameservers, and rDNS queries to their own set and so on).  Adding
+another argument (set of nameservers to use) to EVERY query submitting
+routine is.. insane.  Especially since in 99% cases it will be set to
+default NULL.  But with such "nesting" of query initializers, it becomes
+trivial.

Modified: udns/branches/upstream/trunk/TODO
===================================================================
--- udns/branches/upstream/trunk/TODO	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/branches/upstream/trunk/TODO	2006-12-06 12:57:21 UTC (rev 2991)
@@ -2,6 +2,15 @@
 
 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
@@ -26,6 +35,23 @@
 * dns_init(do_open) - make the parameter opposite, aka
   dns_init(skip_open) ?
 
+* for the above.  Use separate routine for initializing the context
+  from system files, to not link stuff reading resolv.conf if it's
+  not needed.  So that automatic init will not be possible.
+
+* allow TCP queue?
+
+* detect servers which don't understand EDNS0 (returning FORMERR),
+  and fall back to pre-EDNS0 for them.
+
+* for the above to work, we have to be able to find query object by
+  only ID, not ID + qdn.
+
+* And oh, qID should really be random.
+
+* more accurate error reporting.  Currently, udns always returns TEMPFAIL,
+  but don't specify why it happened (ENOMEM, timeout, etc).
+
 * check the error value returned by recvfrom() and
   sendto() and determine which errors to ignore.
 

Modified: udns/branches/upstream/trunk/debian/changelog
===================================================================
--- udns/branches/upstream/trunk/debian/changelog	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/branches/upstream/trunk/debian/changelog	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,3 +1,25 @@
+udns (0.0.9pre) unstable; urgency=low
+
+  * s/EOVERFLOW/ENFILE, partly to make win32 happy
+
+  * several win32 fixes
+
+  * don't use `class' in udns.h, to make C++ happy
+    (thanks Markus Koetter for pointing this out)
+
+  * fixed CNAME handling in dnsget tool.  Another Thank You! goes
+    to Markus Koetter.
+
+  * NAPTR (RFC3403) support, thanks to Mikael Magnusson
+    <mikma at users.sourceforge.net> for this.
+
+  * more Win32 fixes from Mikael Magnusson.  I have to admit
+    I never tried to compile it on Win32.
+
+  * added NOTES file
+
+ -- Michael Tokarev <mjt at corpit.ru>  Wed, 29 Nov 2006 04:16:21 +0300
+
 udns (0.0.8) unstable; urgency=low
 
   * don't compare sockaddr_in's, but individual parts only

Modified: udns/branches/upstream/trunk/debian/rules
===================================================================
--- udns/branches/upstream/trunk/debian/rules	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/branches/upstream/trunk/debian/rules	2006-12-06 12:57:21 UTC (rev 2991)
@@ -62,7 +62,7 @@
 	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
+	dh_installdocs -plibudns-dev TODO NOTES
 	dh_installexamples -plibudns-dev ex-rdns.c
 
 # udns-utils

Modified: udns/branches/upstream/trunk/dnsget.c
===================================================================
--- udns/branches/upstream/trunk/dnsget.c	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/branches/upstream/trunk/dnsget.c	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,4 +1,4 @@
-/* $Id: dnsget.c,v 1.18 2005/05/16 12:43:26 mjt Exp $
+/* $Id: dnsget.c,v 1.22 2006/11/29 21:28:49 mjt Exp $
    simple host/dig-like application using UDNS library
 
    Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
@@ -203,7 +203,7 @@
 
   case DNS_T_AAAA:
     if (rr->dnsrr_dsz != 16) goto xperr;
-    printf("%s", inet_ntop(AF_INET6, dptr, dn, DNS_MAXDN));
+    printf("%s", inet_ntop(AF_INET6, dptr, (char*)dn, DNS_MAXDN));
     break;
 
   case DNS_T_MX:
@@ -262,6 +262,25 @@
            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;
@@ -466,7 +485,7 @@
   struct dns_rr rr;
   unsigned nrr;
   unsigned char dn[DNS_MAXDN];
-  const unsigned char *pkt, *cur, *end, *qdn;
+  const unsigned char *pkt, *cur, *end;
   if (!result) {
     dnserror(q, r);
     return;
@@ -475,10 +494,9 @@
   dns_getdn(pkt, &cur, end, dn, sizeof(dn));
   dns_initparse(&p, NULL, pkt, cur, end);
   p.dnsp_qcls = p.dnsp_qtyp = 0;
-  qdn = dn;
   nrr = 0;
   while((r = dns_nextrr(&p, &rr)) > 0) {
-    if (!dns_dnequal(qdn, rr.dnsrr_dn)) continue;
+    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;
@@ -491,10 +509,10 @@
       }
       else {
         if (verbose == 1) {
-          printf("%s.", dns_dntosp(qdn));
+          printf("%s.", dns_dntosp(dn));
           printf(" CNAME %s.\n", dns_dntosp(p.dnsp_dnbuf));
         }
-        qdn = p.dnsp_dnbuf;
+	dns_dntodn(p.dnsp_dnbuf, dn, sizeof(dn));
       }
     }
   }

Modified: udns/branches/upstream/trunk/udns.3
===================================================================
--- udns/branches/upstream/trunk/udns.3	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/branches/upstream/trunk/udns.3	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,4 +1,4 @@
-.\" $Id: udns.3,v 1.25 2005/09/12 12:05:12 mjt Exp $
+.\" $Id: udns.3,v 1.26 2006/11/28 22:58:04 mjt Exp $
 .\" udns library manpage
 .\"
 .\" Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
@@ -810,6 +810,48 @@
 interest (if the \fIname\fR is absolute, that is, it ends up with a dot,
 DNS_NOSRCH flag will be set automatically).
 
+.SS "NAPTR Queries"
+.PP
+.nf
+struct \fBdns_naptr\fR {        /* single NAPTR record */
+  int \fBorder\fR;              /* record order */
+  int \fBpreference\fR;         /* preference of this record */
+  char *\fBflags\fR;            /* application-specific flags */
+  char *\fBservices\fR;         /* service parameters */
+  char *\fBregexp\fR;           /* substitutional regular expression */
+  char *\fBreplacement\fR;      /* replacement string */
+};
+struct \fBdns_rr_naptr\fR {     /* NAPTR RRset */
+  char *\fBdnsnaptr_qname\fR;   /* original query name */
+  char *\fBdnsnaptr_cname\fR;   /* canonical name */
+  unsigned \fBdnsnaptr_ttl\fR;  /* Time-To-Live (TTL) value */
+  int \fBdnsnaptr_nrr\fR;       /* number of text records in the set */
+  struct dns_naptr \fBdnsnaptr_naptr\fR[]; /* array of NAPTR records */
+};
+typedef void
+  \fBdns_query_naptr_fn\fR(\fIctx\fR, struct dns_rr_naptr *\fIresult\fR, \fIdata\fR)
+dns_parse_fn \fBdns_parse_naptr\fB;
+struct dns_query *
+\fBdns_submit_naptr\fB(\fIctx\fR, const char *\fIname\fR, int \fIflags\fR,
+   dns_query_txt_fn *\fIcbck\fR, \fIdata\fR);
+struct dns_rr_naptr *
+\fBdns_resolve_naptr\fB(\fIctx\fR, const char *\fIname\fR, int \fIflags\fR);
+.fi
+.PP
+The \fBdns_rr_naptr\fR structure holds a result of an IN NAPTR (rfc3403) query.
+Callback routine for IN NAPTR queries expected to be of type
+\fBdns_query_naptr_fn\fR, expects pointer to \fBdns_rr_naptr\fR
+structure as query result instead of raw DNS packet.
+The \fBdns_parse_naptr\fR() is used to convert raw DNS reply packet into
+\fBdns_rr_naptr\fR structure (it is used
+internally and may be used directly too with generic query interface).
+Routines \fBdns_submit_naptr\fR() and \fBdns_resolve_naptr\fR() are used to
+perform IN NAPTR queries in a type-safe manner.  The \fIname\fR parameter
+is the domain name in question, and \fIflags\fR is query flags bitmask,
+with one bit, DNS_NOSRCH, of practical interest (if the \fIname\fR is
+absolute, that is, it ends up with a dot, DNS_NOSRCH flag will be set
+automatically).
+
 .SS "DNSBL Interface"
 .PP
 A DNS-based blocklists, or a DNSBLs, are in wide use nowadays, especially

Modified: udns/branches/upstream/trunk/udns.h
===================================================================
--- udns/branches/upstream/trunk/udns.h	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/branches/upstream/trunk/udns.h	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,4 +1,4 @@
-/* $Id: udns.h,v 1.37 2005/09/12 12:09:10 mjt Exp $
+/* $Id: udns.h,v 1.41 2006/11/29 01:20:30 mjt Exp $
    header file for the UDNS library.
 
    Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
@@ -23,7 +23,7 @@
 
 #ifndef UDNS_VERSION	/* include guard */
 
-#define UDNS_VERSION "0.0.8"
+#define UDNS_VERSION "0.0.9pre"
 
 #ifdef WIN32
 # ifdef UDNS_DYNAMIC_LIBRARY
@@ -479,8 +479,7 @@
 UDNS_API int
 dns_cancel(struct dns_ctx *ctx, struct dns_query *q);
 
-/* immediately resolve a generic query, return the answer
- * and place completion status into *statusp */
+/* 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,
@@ -636,8 +635,34 @@
                 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);
@@ -693,11 +718,11 @@
 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(class) dns_findname(dns_classtab, (class))
+#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 class);
+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);

Modified: udns/branches/upstream/trunk/udns_dn.c
===================================================================
--- udns/branches/upstream/trunk/udns_dn.c	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/branches/upstream/trunk/udns_dn.c	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,4 +1,4 @@
-/* $Id: udns_dn.c,v 1.6 2005/09/12 10:55:21 mjt Exp $
+/* $Id: udns_dn.c,v 1.7 2006/11/28 22:45:20 mjt Exp $
    domain names manipulation routines
 
    Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
@@ -71,7 +71,7 @@
   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(np));
+  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 */
 

Modified: udns/branches/upstream/trunk/udns_resolver.c
===================================================================
--- udns/branches/upstream/trunk/udns_resolver.c	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/branches/upstream/trunk/udns_resolver.c	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,4 +1,4 @@
-/* $Id: udns_resolver.c,v 1.53 2005/09/12 10:23:08 mjt Exp $
+/* $Id: udns_resolver.c,v 1.57 2006/11/29 01:17:43 mjt Exp $
    resolver stuff (main module)
 
    Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
@@ -24,6 +24,8 @@
 #ifdef WIN32
 # include <winsock2.h>          /* includes <windows.h> */
 # include <ws2tcpip.h>          /* needed for struct in6_addr */
+# include <iphlpapi.h>		/* for dns server addresses etc */
+# undef HAVE_POLL
 #else
 # include <sys/types.h>
 # include <sys/socket.h>
@@ -255,7 +257,7 @@
   if (!serv)
     return (ctx->dnsc_nserv = 0);
   if (ctx->dnsc_nserv >= DNS_MAXSERV)
-    return errno = EOVERFLOW, -1;
+    return errno = ENFILE, -1;
   sns = &ctx->dnsc_serv[ctx->dnsc_nserv];
   memset(sns, 0, sizeof(*sns));
 #if HAVE_INET6
@@ -301,7 +303,7 @@
   if (!sa)
     return (ctx->dnsc_nserv = 0);
   if (ctx->dnsc_nserv >= DNS_MAXSERV)
-    return errno = EOVERFLOW, -1;
+    return errno = ENFILE, -1;
 #if HAVE_INET6
   else if (sa->sa_family == AF_INET6)
     ctx->dnsc_serv[ctx->dnsc_nserv].sin6 = *(struct sockaddr_in6*)sa;
@@ -380,7 +382,7 @@
   if (!srch)
     return (ctx->dnsc_nsrch = 0);
   else if (ctx->dnsc_nsrch >= DNS_MAXSRCH)
-    return errno = EOVERFLOW, -1;
+    return errno = ENFILE, -1;
   else if (dns_sptodn(srch, ctx->dnsc_srch[ctx->dnsc_nsrch], DNS_MAXDN) <= 0)
     return errno = EINVAL, -1;
   else
@@ -461,17 +463,17 @@
   int ret = -1;
 
   h_iphlpapi = LoadLibrary("iphlpapi.dll");
-  if (h_iphlpapi == HANDLE_ERROR)
+  if (!h_iphlpapi)
     return -1;
   pfnGetAdAddrs = (GetAdaptersAddressesFunc)
-    GetProcAddress(iphlp, "GetAdaptersAddresses");
+    GetProcAddress(h_iphlpapi, "GetAdaptersAddresses");
   if (!pfnGetAdAddrs) goto freelib;
   ulOutBufLen = 0;
-  dwRetVal = GetAdAddrs(AF_UNSPEC, 0, NULL, NULL, &ulOutBufLen);
+  dwRetVal = pfnGetAdAddrs(AF_UNSPEC, 0, NULL, NULL, &ulOutBufLen);
   if (dwRetVal != ERROR_BUFFER_OVERFLOW) goto freelib;
   pAddrBuf = malloc(ulOutBufLen);
   if (!pAddrBuf) goto freelib;
-  dwRetVal = GetAdAddrs(AF_UNSPEC, 0, NULL, pAddrBuf, &ulOutBufLen);
+  dwRetVal = pfnGetAdAddrs(AF_UNSPEC, 0, NULL, pAddrBuf, &ulOutBufLen);
   if (dwRetVal != ERROR_SUCCESS) goto freemem;
   for (pAddr = pAddrBuf;
        pAddr && ctx->dnsc_nserv <= DNS_MAXSERV;
@@ -507,7 +509,7 @@
   res = RegQueryValueEx(hk, "NameServer", NULL, &type, valBuf, &len);
   if (res != ERROR_SUCCESS || !len || !valBuf[0]) {
     len = sizeof(valBuf) - 1;
-    res = RegQueryValueEx(hk, "DhcpNameServer", &type, valBuf, &len);
+    res = RegQueryValueEx(hk, "DhcpNameServer", NULL, &type, valBuf, &len);
   }
   RegCloseKey(hk);
   if (res != ERROR_SUCCESS || !len || !valBuf[0])
@@ -751,7 +753,7 @@
 void dns_close(struct dns_ctx *ctx) {
   SETCTXINITED(ctx);
   if (ctx->dnsc_udpsock < 0) return;
-  close(ctx->dnsc_udpsock);
+  closesocket(ctx->dnsc_udpsock);
   ctx->dnsc_udpsock = -1;
   free(ctx->dnsc_pbuf);
   ctx->dnsc_pbuf = NULL;
@@ -1039,7 +1041,7 @@
        * remote errors should be ignored (for now anyway).
        */
 #ifdef WIN32
-      if (WSAGetLastError() != WSAEWOULDBLOCK)
+      if (WSAGetLastError() == WSAEWOULDBLOCK)
 #else
       if (errno == EAGAIN)
 #endif
@@ -1250,9 +1252,6 @@
 
 void *dns_resolve(struct dns_ctx *ctx, struct dns_query *q) {
   time_t now;
-#ifdef WIN32
-# warning fixme: poll()/select() on WIN32 (WaitForMultipleObjects?)
-#endif
 #ifdef HAVE_POLL
   struct pollfd pfd;
 #else

Added: udns/branches/upstream/trunk/udns_rr_naptr.c
===================================================================
--- udns/branches/upstream/trunk/udns_rr_naptr.c	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/branches/upstream/trunk/udns_rr_naptr.c	2006-12-06 12:57:21 UTC (rev 2991)
@@ -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 at corpit.ru>
+   Copyright (C) 2006  Mikael Magnusson <mikma at users.sourceforge.net>
+   This file is part of UDNS library, an async DNS stub resolver.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library, in file named COPYING.LGPL; if not,
+   write to the Free Software Foundation, Inc., 59 Temple Place,
+   Suite 330, Boston, MA  02111-1307  USA
+
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "udns.h"
+
+/* Get a single string for NAPTR record, pretty much like a DN label.
+ * String length is in first byte in *cur, so it can't be >255.
+ */
+static int dns_getstr(dnscc_t **cur, dnscc_t *ep, char *buf)
+{
+  unsigned l;
+  dnscc_t *cp = *cur;
+
+  l = *cp++;
+  if (cp + l > ep)
+    return DNS_E_PROTOCOL;
+  if (buf) {
+    memcpy(buf, cp, l);
+    buf[l] = '\0';
+  }
+  cp += l;
+
+  *cur = cp;
+  return l + 1;
+}
+
+int
+dns_parse_naptr(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
+                void **result) {
+  struct dns_rr_naptr *ret;
+  struct dns_parse p;
+  struct dns_rr rr;
+  int r, l;
+  char *sp;
+  dnsc_t dn[DNS_MAXDN];
+
+  assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_NAPTR);
+
+  /* first, validate the answer and count size of the result */
+  l = 0;
+  dns_initparse(&p, qdn, pkt, cur, end);
+  while((r = dns_nextrr(&p, &rr)) > 0) {
+    int i;
+    dnscc_t *ep = rr.dnsrr_dend;
+
+    /* first 4 bytes: order & preference */
+    cur = rr.dnsrr_dptr + 4;
+
+    /* flags, services and regexp */
+    for (i = 0; i < 3; i++) {
+      r = dns_getstr(&cur, ep, NULL);
+      if (r < 0)
+        return r;
+      l += r;
+    }
+    /* replacement */
+    r = dns_getdn(pkt, &cur, end, dn, sizeof(dn));
+    if (r <= 0 || cur != rr.dnsrr_dend)
+      return DNS_E_PROTOCOL;
+    l += dns_dntop_size(dn);
+  }
+  if (r < 0)
+    return DNS_E_PROTOCOL;
+  if (!p.dnsp_nrr)
+    return DNS_E_NODATA;
+
+  /* next, allocate and set up result */
+  l += dns_stdrr_size(&p);
+  ret = malloc(sizeof(*ret) + sizeof(struct dns_naptr) * p.dnsp_nrr + l);
+  if (!ret)
+    return DNS_E_NOMEM;
+  ret->dnsnaptr_nrr = p.dnsp_nrr;
+  ret->dnsnaptr_naptr = (struct dns_naptr *)(ret+1);
+
+  /* and 3rd, fill in result, finally */
+  sp = (char*)(&ret->dnsnaptr_naptr[p.dnsp_nrr]);
+  for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r) {
+    cur = rr.dnsrr_dptr;
+    ret->dnsnaptr_naptr[r].order = dns_get16(cur); cur += 2;
+    ret->dnsnaptr_naptr[r].preference = dns_get16(cur); cur += 2;
+    sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].flags = sp));
+    sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].service = sp));
+    sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].regexp = sp));
+    dns_getdn(pkt, &cur, end, dn, sizeof(dn));
+    sp += dns_dntop(dn, (ret->dnsnaptr_naptr[r].replacement = sp), DNS_MAXNAME);
+  }
+  dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p);
+  *result = ret;
+  return 0;
+}
+
+struct dns_query *
+dns_submit_naptr(struct dns_ctx *ctx, const char *name, int flags,
+                 dns_query_naptr_fn *cbck, void *data) {
+  return
+    dns_submit_p(ctx, name, DNS_C_IN, DNS_T_NAPTR, flags,
+                 dns_parse_naptr, (dns_query_fn *)cbck, data);
+}
+
+struct dns_rr_naptr *
+dns_resolve_naptr(struct dns_ctx *ctx, const char *name, int flags) {
+  return (struct dns_rr_naptr *)
+    dns_resolve_p(ctx, name, DNS_C_IN, DNS_T_NAPTR, flags, dns_parse_naptr);
+}


Property changes on: udns/branches/upstream/trunk/udns_rr_naptr.c
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Modified: udns/branches/upstream/trunk/udns_rr_txt.c
===================================================================
--- udns/branches/upstream/trunk/udns_rr_txt.c	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/branches/upstream/trunk/udns_rr_txt.c	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,4 +1,4 @@
-/* $Id: udns_rr_txt.c,v 1.14 2005/04/20 06:44:34 mjt Exp $
+/* $Id: udns_rr_txt.c,v 1.15 2006/11/28 22:45:20 mjt Exp $
    parse/query TXT records
 
    Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
@@ -78,7 +78,7 @@
     ret->dnstxt_txt[r].len = sp - ret->dnstxt_txt[r].txt;
     *sp++ = '\0';
   }
-  dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p);
+  dns_stdrr_finish((struct dns_rr_null *)ret, (char*)sp, &p);
   *result = ret;
   return 0;
 }

Copied: udns/tags/upstream/0.0.9pre (from rev 2990, udns/branches/upstream/trunk)

Modified: udns/tags/upstream/0.0.9pre/Makefile
===================================================================
--- udns/branches/upstream/trunk/Makefile	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/tags/upstream/0.0.9pre/Makefile	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,5 +1,5 @@
 #! /usr/bin/make -rf
-# $Id: Makefile,v 1.38 2005/09/12 12:09:10 mjt Exp $
+# $Id: Makefile,v 1.42 2006/11/29 21:27:01 mjt Exp $
 # libudns Makefile
 #
 # Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
@@ -20,13 +20,14 @@
 # write to the Free Software Foundation, Inc., 59 Temple Place,
 # Suite 330, Boston, MA  02111-1307  USA
 
-VERS   = 0.0.8
+VERS   = 0.0.9pre
 SRCS   = udns_dn.c udns_dntosp.c udns_parse.c udns_resolver.c udns_misc.c \
 	udns_rr_a.c udns_rr_ptr.c udns_rr_mx.c udns_rr_txt.c udns_bl.c \
-	udns_rr_srv.c udns_codes.c
+	udns_rr_srv.c udns_rr_naptr.c udns_codes.c
 USRCS  = dnsget.c rblcheck.c ex-rdns.c
+DEB    = debian/copyright debian/changelog debian/control debian/rules
 DIST   = COPYING.LGPL udns.h udns.3 dnsget.1 rblcheck.1 $(SRCS) $(USRCS) \
-	Makefile TODO
+	Makefile TODO NOTES
 
 OBJS   = $(SRCS:.c=.o) $(GEN:.c=.o)
 LIB    = libudns.a
@@ -114,9 +115,10 @@
 	mv $@.tmp $@
 
 dist: $(NAMEPFX).tar.gz
-$(NAMEPFX).tar.gz: $(DIST)
-	mkdir $(NAMEPFX)
+$(NAMEPFX).tar.gz: $(DIST) $(DEB)
+	mkdir $(NAMEPFX) $(NAMEPFX)/debian
 	ln $(DIST) $(NAMEPFX)
+	ln $(DEB) $(NAMEPFX)/debian
 	tar cvfz $@ $(NAMEPFX)
 	rm -rf $(NAMEPFX)
 subdist:

Added: udns/tags/upstream/0.0.9pre/NOTES
===================================================================
--- udns/branches/upstream/trunk/NOTES	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/tags/upstream/0.0.9pre/NOTES	2006-12-06 12:57:21 UTC (rev 2991)
@@ -0,0 +1,193 @@
+Assorted notes about udns (library).
+
+UDP-only mode
+~~~~~~~~~~~~~
+
+First of all, since udns is (currently) UDP-only, there are some
+shortcomings.
+
+It assumes that a reply will fit into a UDP buffer.  With adoption of EDNS0,
+and general robustness of IP stacks, in most cases it's not an issue.  But
+in some cases there may be problems:
+
+ - if an RRset is "very large" so it does not fit even in buffer of size
+   requested by the library (current default is 4096; some servers limits
+   it further), we will not see the reply, or will only see "damaged"
+   reply (depending on the server)
+
+ - many DNS servers ignores EDNS0 option requests.  In this case, no matter
+   which buffer size udns library will request, such servers reply is limited
+   to 512 bytes (standard pre-EDNS0 DNS packet size).
+
+ - some DNS servers, notable the ones used by Verisign for certain top-level
+   domains, chokes on EDNS0-enabled queries, returning FORMERR.  Such
+   behavior isn't prohibited by DNS standards, but in my opinion it's at
+   least weird - the server can easily ignore EDNS0 options and send a
+   reply, instead of sending error.
+   Currently, udns does nothing in this situation, completely ignoring the
+   error returned by the server, and continue waiting for reply.  It probably
+   should grok that this server does not understand EDNS0 and retry w/o the
+   options, but it does not.  The end result - esp. if your local DNS
+   server or - worse - broken firewall which inspects DNS packets and drops
+   the ones which - from its point of view - are "broken" - is that you
+   see only TEMPFAIL errors from the library trying to resolve ANY names.
+
+Implementing TCP mode (together with non-EDNS0 fall-back as above) isn't
+difficult, but it complicates API significantly.  Currently udns uses only
+single UDP socket (or - maybe in the future - two, see below), but in case of
+TCP, it will need to open and close sockets for TCP connections left and
+right, and that have to be integrated into an application's event loop in
+an easy and efficient way.  Plus all the timeouts - different for connect(),
+write, and several stages of read.
+
+IPv6 vs IPv4 usage
+~~~~~~~~~~~~~~~~~~
+
+This is only relevant for nameservers reachable over IPv6, NOT for IPv6
+queries.  I.e., if you've IPv6 addresses in 'nameservers' line in your
+/etc/resolv.conf file.  Even more: if you have BOTH IPv6 AND IPv4 addresses
+there.  Or pass them to udns initialization routines.
+
+Since udns uses a single UDP socket to communicate with all nameservers,
+it should support both v4 and v6 communications.  Most current platforms
+supports this mode - using PF_INET6 socket and V4MAPPED addresses, i.e,
+"tunnelling" IPv4 inside IPv6.  But not all systems supports this.  And
+more, it has been said that such mode is deprecated.
+
+So, list only IPv4 or only IPv6 addresses, but don't mix them, in your
+/etc/resolv.conf.
+
+An alternative is to use two sockets instead of 1 - one for IPv6 and one
+for IPv4.  For now I'm not sure if it's worth the complexity - again, of
+the API, not the library itself (but this will not simplify library either).
+
+Single socket for all queries
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Using single UDP socket for sending queries to all nameservers has obvious
+advantages.  First it's, again, trivial, simple to use API.  And simple
+library too.  Also, after sending queries to all nameservers (in case first
+didn't reply in time), we will be able to receive late reply from first
+nameserver and accept it.
+
+But this mode has disadvantages too.  Most important is that it's much easier
+to send fake reply to us, as the UDP port where we expects the reply to come
+to is constant during the whole lifetime of an application.  More secure
+implementations uses random port for every single query.  While port number
+(16 bits integer) can not hold much randomness, it's still of some help.
+Ok, udns is a stub resolver, so it expects sorta friendly environment, but
+on LAN it's usually much easier to fire an attack, due to the speed of local
+network, where a bad guy can generate alot of packets in a short time.
+
+Choosing of DNS QueryID
+~~~~~~~~~~~~~~~~~~~~~~~
+
+This is more a TODO item really.  Currently, udns uses sequential number for
+query IDs.  Which simplifies attacks even more (c.f. the previous item about
+single UDP port), making them nearly trivial.  The library should use random
+number for query ID.  But there's no portable way to get random numbers, even
+on various flavors of Unix.  It's possible to use low bits from tv_nsec field
+returned by gettimeofday() (current time, nanoseconds), but I wrote the library
+in a way to avoid making system calls where possible, because many syscalls
+means many context switches and slow processes as a result.  Maybe use some
+application-supplied callback to get random values will be a better way,
+defaulting to gettimeofday() method.
+
+Note that a single query - even if (re)sent to different nameservers, several
+times (due to no reply received in time), uses the same qID assigned when it
+was first dispatched.  So we have: single UDP socket (fixed port number),
+sequential (= trivially predictable) qIDs, and long lifetime of those qIDs.
+This all makes (local) attacks against the library really trivial.
+
+Assumptions about RRs returned
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Currently udns processes records in the reply it received sequentially.
+This means that order of the records is significant.  For example, if
+we asked for foo.bar A, but the server returned that foo.bar is a CNAME
+(alias) for bar.baz, and bar.baz, in turn, has address 1.2.3.4, when
+the CNAME should come first in reply, followed by A.  While DNS specs
+does not say anything about order of records - it's an rrSET - unordered, -
+I think an implementation which returns the records in "wrong" order is
+somewhat insane...  Well ok, to be fair, I don't really remember how
+udns handles this now - need to check this in source... ;)
+
+CNAME recursion
+~~~~~~~~~~~~~~~
+
+Another dark point of udns is the handling of CNAMEs returned as replies
+to non-CNAME queries.  If we asked for foo.bar A, but it's a CNAME, udns
+expects BOTH the CNAME itself and the target DN to be present in the reply.
+In other words, udns DOES NOT RECURSE CNAMES.  If we asked for foo.bar A,
+but only record in reply was that foo.bar is a CNAME for bar.baz, udns will
+return no records to an application (NXDOMAIN).  Strictly speaking, udns
+should repeat the query asking for bar.baz A, and recurse.  But since it's
+stub resolver, recursive resolver should recurse for us instead.
+
+It's not very difficult to implement, however.  Probably with some (global?)
+flag to en/dis-able the feature.  Provided there's some demand for it.
+
+To clarify: udns handles CNAME recursion in a single reply packet just fine.
+
+Error reporting
+~~~~~~~~~~~~~~~
+
+Too many places in the code (various failure paths) sets generic "TEMPFAIL"
+error condition.  For example, if no nameserver replied to our query, an
+application will get generic TEMPFAIL, instead of something like TIMEDOUT.
+This probably should be fixed, but most applications don't care about the
+exact reasons of failure - 4 common cases are already too much:
+  - query returned some valid data
+  - NXDOMAIN
+  - valid domain but no data of requested type - =NXDOMAIN in most cases
+  - temporary error - this one sometimes (incorrectly!) treated as NXDOMAIN
+    by (naive) applications.
+DNS isn't yes/no, it's at least 3 variants, temp err being the 3rd important
+case!  And adding more variations for the temp error case is complicating things
+even more - again, from an application writer standpoint.  For diagnostics,
+such more specific error cases are of good help.
+
+Planned API changes
+~~~~~~~~~~~~~~~~~~~
+
+At least one thing I want to change for 0.1 version is a way how queries are
+submitted.
+
+I want to made dns_query object to be owned by an application.  So that instead
+of udns library allocating it for the lifetime of query, it will be pre-
+allocated by an application.  This simplifies and enhances query submitting
+interface, and complicates it a bit too, in simplest cases.
+
+Currently, we have:
+
+dns_submit_dn(dn, cls, typ, flags, parse, cbck, data)
+dns_submit_p(name, cls, typ, flags, parse, cbck, data)
+dns_submit_a4(ctx, name, flags, cbck, data)
+
+and so on -- with many parameters missed for type-specific cases, but generic
+cases being too complex for most common usage.
+
+Instead, with dns_query being owned by an app, we will be able to separately
+set up various parts of the query - domain name (various forms), type&class,
+parser, flags, callback...  and even change them at runtime.  And we will also
+be able to reuse query structures, instead of allocating/freeing them every
+time.  So the whole thing will look something like:
+
+ q = dns_alloc_query();
+ dns_submit(dns_q_flags(dns_q_a4(q, name, cbck), DNS_F_NOSRCH), data);
+
+The idea is to have a set of functions accepting struct dns_query* and
+returning it (so the calls can be "nested" like the above), to set up
+relevant parts of the query - specific type of callback, conversion from
+(type-specific) query parameters into a domain name (this is for type-
+specific query initializers), and setting various flags and options and
+type&class things.
+
+One example where this is almost essential - if we want to support
+per-query set of nameservers (which isn't at all useless: imagine a
+high-volume mail server, were we want to direct DNSBL queries to a separate
+set of nameservers, and rDNS queries to their own set and so on).  Adding
+another argument (set of nameservers to use) to EVERY query submitting
+routine is.. insane.  Especially since in 99% cases it will be set to
+default NULL.  But with such "nesting" of query initializers, it becomes
+trivial.

Modified: udns/tags/upstream/0.0.9pre/TODO
===================================================================
--- udns/branches/upstream/trunk/TODO	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/tags/upstream/0.0.9pre/TODO	2006-12-06 12:57:21 UTC (rev 2991)
@@ -2,6 +2,15 @@
 
 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
@@ -26,6 +35,23 @@
 * dns_init(do_open) - make the parameter opposite, aka
   dns_init(skip_open) ?
 
+* for the above.  Use separate routine for initializing the context
+  from system files, to not link stuff reading resolv.conf if it's
+  not needed.  So that automatic init will not be possible.
+
+* allow TCP queue?
+
+* detect servers which don't understand EDNS0 (returning FORMERR),
+  and fall back to pre-EDNS0 for them.
+
+* for the above to work, we have to be able to find query object by
+  only ID, not ID + qdn.
+
+* And oh, qID should really be random.
+
+* more accurate error reporting.  Currently, udns always returns TEMPFAIL,
+  but don't specify why it happened (ENOMEM, timeout, etc).
+
 * check the error value returned by recvfrom() and
   sendto() and determine which errors to ignore.
 

Modified: udns/tags/upstream/0.0.9pre/debian/changelog
===================================================================
--- udns/branches/upstream/trunk/debian/changelog	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/tags/upstream/0.0.9pre/debian/changelog	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,3 +1,25 @@
+udns (0.0.9pre) unstable; urgency=low
+
+  * s/EOVERFLOW/ENFILE, partly to make win32 happy
+
+  * several win32 fixes
+
+  * don't use `class' in udns.h, to make C++ happy
+    (thanks Markus Koetter for pointing this out)
+
+  * fixed CNAME handling in dnsget tool.  Another Thank You! goes
+    to Markus Koetter.
+
+  * NAPTR (RFC3403) support, thanks to Mikael Magnusson
+    <mikma at users.sourceforge.net> for this.
+
+  * more Win32 fixes from Mikael Magnusson.  I have to admit
+    I never tried to compile it on Win32.
+
+  * added NOTES file
+
+ -- Michael Tokarev <mjt at corpit.ru>  Wed, 29 Nov 2006 04:16:21 +0300
+
 udns (0.0.8) unstable; urgency=low
 
   * don't compare sockaddr_in's, but individual parts only

Modified: udns/tags/upstream/0.0.9pre/debian/rules
===================================================================
--- udns/branches/upstream/trunk/debian/rules	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/tags/upstream/0.0.9pre/debian/rules	2006-12-06 12:57:21 UTC (rev 2991)
@@ -62,7 +62,7 @@
 	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
+	dh_installdocs -plibudns-dev TODO NOTES
 	dh_installexamples -plibudns-dev ex-rdns.c
 
 # udns-utils

Modified: udns/tags/upstream/0.0.9pre/dnsget.c
===================================================================
--- udns/branches/upstream/trunk/dnsget.c	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/tags/upstream/0.0.9pre/dnsget.c	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,4 +1,4 @@
-/* $Id: dnsget.c,v 1.18 2005/05/16 12:43:26 mjt Exp $
+/* $Id: dnsget.c,v 1.22 2006/11/29 21:28:49 mjt Exp $
    simple host/dig-like application using UDNS library
 
    Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
@@ -203,7 +203,7 @@
 
   case DNS_T_AAAA:
     if (rr->dnsrr_dsz != 16) goto xperr;
-    printf("%s", inet_ntop(AF_INET6, dptr, dn, DNS_MAXDN));
+    printf("%s", inet_ntop(AF_INET6, dptr, (char*)dn, DNS_MAXDN));
     break;
 
   case DNS_T_MX:
@@ -262,6 +262,25 @@
            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;
@@ -466,7 +485,7 @@
   struct dns_rr rr;
   unsigned nrr;
   unsigned char dn[DNS_MAXDN];
-  const unsigned char *pkt, *cur, *end, *qdn;
+  const unsigned char *pkt, *cur, *end;
   if (!result) {
     dnserror(q, r);
     return;
@@ -475,10 +494,9 @@
   dns_getdn(pkt, &cur, end, dn, sizeof(dn));
   dns_initparse(&p, NULL, pkt, cur, end);
   p.dnsp_qcls = p.dnsp_qtyp = 0;
-  qdn = dn;
   nrr = 0;
   while((r = dns_nextrr(&p, &rr)) > 0) {
-    if (!dns_dnequal(qdn, rr.dnsrr_dn)) continue;
+    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;
@@ -491,10 +509,10 @@
       }
       else {
         if (verbose == 1) {
-          printf("%s.", dns_dntosp(qdn));
+          printf("%s.", dns_dntosp(dn));
           printf(" CNAME %s.\n", dns_dntosp(p.dnsp_dnbuf));
         }
-        qdn = p.dnsp_dnbuf;
+	dns_dntodn(p.dnsp_dnbuf, dn, sizeof(dn));
       }
     }
   }

Modified: udns/tags/upstream/0.0.9pre/udns.3
===================================================================
--- udns/branches/upstream/trunk/udns.3	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/tags/upstream/0.0.9pre/udns.3	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,4 +1,4 @@
-.\" $Id: udns.3,v 1.25 2005/09/12 12:05:12 mjt Exp $
+.\" $Id: udns.3,v 1.26 2006/11/28 22:58:04 mjt Exp $
 .\" udns library manpage
 .\"
 .\" Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
@@ -810,6 +810,48 @@
 interest (if the \fIname\fR is absolute, that is, it ends up with a dot,
 DNS_NOSRCH flag will be set automatically).
 
+.SS "NAPTR Queries"
+.PP
+.nf
+struct \fBdns_naptr\fR {        /* single NAPTR record */
+  int \fBorder\fR;              /* record order */
+  int \fBpreference\fR;         /* preference of this record */
+  char *\fBflags\fR;            /* application-specific flags */
+  char *\fBservices\fR;         /* service parameters */
+  char *\fBregexp\fR;           /* substitutional regular expression */
+  char *\fBreplacement\fR;      /* replacement string */
+};
+struct \fBdns_rr_naptr\fR {     /* NAPTR RRset */
+  char *\fBdnsnaptr_qname\fR;   /* original query name */
+  char *\fBdnsnaptr_cname\fR;   /* canonical name */
+  unsigned \fBdnsnaptr_ttl\fR;  /* Time-To-Live (TTL) value */
+  int \fBdnsnaptr_nrr\fR;       /* number of text records in the set */
+  struct dns_naptr \fBdnsnaptr_naptr\fR[]; /* array of NAPTR records */
+};
+typedef void
+  \fBdns_query_naptr_fn\fR(\fIctx\fR, struct dns_rr_naptr *\fIresult\fR, \fIdata\fR)
+dns_parse_fn \fBdns_parse_naptr\fB;
+struct dns_query *
+\fBdns_submit_naptr\fB(\fIctx\fR, const char *\fIname\fR, int \fIflags\fR,
+   dns_query_txt_fn *\fIcbck\fR, \fIdata\fR);
+struct dns_rr_naptr *
+\fBdns_resolve_naptr\fB(\fIctx\fR, const char *\fIname\fR, int \fIflags\fR);
+.fi
+.PP
+The \fBdns_rr_naptr\fR structure holds a result of an IN NAPTR (rfc3403) query.
+Callback routine for IN NAPTR queries expected to be of type
+\fBdns_query_naptr_fn\fR, expects pointer to \fBdns_rr_naptr\fR
+structure as query result instead of raw DNS packet.
+The \fBdns_parse_naptr\fR() is used to convert raw DNS reply packet into
+\fBdns_rr_naptr\fR structure (it is used
+internally and may be used directly too with generic query interface).
+Routines \fBdns_submit_naptr\fR() and \fBdns_resolve_naptr\fR() are used to
+perform IN NAPTR queries in a type-safe manner.  The \fIname\fR parameter
+is the domain name in question, and \fIflags\fR is query flags bitmask,
+with one bit, DNS_NOSRCH, of practical interest (if the \fIname\fR is
+absolute, that is, it ends up with a dot, DNS_NOSRCH flag will be set
+automatically).
+
 .SS "DNSBL Interface"
 .PP
 A DNS-based blocklists, or a DNSBLs, are in wide use nowadays, especially

Modified: udns/tags/upstream/0.0.9pre/udns.h
===================================================================
--- udns/branches/upstream/trunk/udns.h	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/tags/upstream/0.0.9pre/udns.h	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,4 +1,4 @@
-/* $Id: udns.h,v 1.37 2005/09/12 12:09:10 mjt Exp $
+/* $Id: udns.h,v 1.41 2006/11/29 01:20:30 mjt Exp $
    header file for the UDNS library.
 
    Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
@@ -23,7 +23,7 @@
 
 #ifndef UDNS_VERSION	/* include guard */
 
-#define UDNS_VERSION "0.0.8"
+#define UDNS_VERSION "0.0.9pre"
 
 #ifdef WIN32
 # ifdef UDNS_DYNAMIC_LIBRARY
@@ -479,8 +479,7 @@
 UDNS_API int
 dns_cancel(struct dns_ctx *ctx, struct dns_query *q);
 
-/* immediately resolve a generic query, return the answer
- * and place completion status into *statusp */
+/* 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,
@@ -636,8 +635,34 @@
                 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);
@@ -693,11 +718,11 @@
 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(class) dns_findname(dns_classtab, (class))
+#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 class);
+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);

Modified: udns/tags/upstream/0.0.9pre/udns_dn.c
===================================================================
--- udns/branches/upstream/trunk/udns_dn.c	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/tags/upstream/0.0.9pre/udns_dn.c	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,4 +1,4 @@
-/* $Id: udns_dn.c,v 1.6 2005/09/12 10:55:21 mjt Exp $
+/* $Id: udns_dn.c,v 1.7 2006/11/28 22:45:20 mjt Exp $
    domain names manipulation routines
 
    Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
@@ -71,7 +71,7 @@
   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(np));
+  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 */
 

Modified: udns/tags/upstream/0.0.9pre/udns_resolver.c
===================================================================
--- udns/branches/upstream/trunk/udns_resolver.c	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/tags/upstream/0.0.9pre/udns_resolver.c	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,4 +1,4 @@
-/* $Id: udns_resolver.c,v 1.53 2005/09/12 10:23:08 mjt Exp $
+/* $Id: udns_resolver.c,v 1.57 2006/11/29 01:17:43 mjt Exp $
    resolver stuff (main module)
 
    Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
@@ -24,6 +24,8 @@
 #ifdef WIN32
 # include <winsock2.h>          /* includes <windows.h> */
 # include <ws2tcpip.h>          /* needed for struct in6_addr */
+# include <iphlpapi.h>		/* for dns server addresses etc */
+# undef HAVE_POLL
 #else
 # include <sys/types.h>
 # include <sys/socket.h>
@@ -255,7 +257,7 @@
   if (!serv)
     return (ctx->dnsc_nserv = 0);
   if (ctx->dnsc_nserv >= DNS_MAXSERV)
-    return errno = EOVERFLOW, -1;
+    return errno = ENFILE, -1;
   sns = &ctx->dnsc_serv[ctx->dnsc_nserv];
   memset(sns, 0, sizeof(*sns));
 #if HAVE_INET6
@@ -301,7 +303,7 @@
   if (!sa)
     return (ctx->dnsc_nserv = 0);
   if (ctx->dnsc_nserv >= DNS_MAXSERV)
-    return errno = EOVERFLOW, -1;
+    return errno = ENFILE, -1;
 #if HAVE_INET6
   else if (sa->sa_family == AF_INET6)
     ctx->dnsc_serv[ctx->dnsc_nserv].sin6 = *(struct sockaddr_in6*)sa;
@@ -380,7 +382,7 @@
   if (!srch)
     return (ctx->dnsc_nsrch = 0);
   else if (ctx->dnsc_nsrch >= DNS_MAXSRCH)
-    return errno = EOVERFLOW, -1;
+    return errno = ENFILE, -1;
   else if (dns_sptodn(srch, ctx->dnsc_srch[ctx->dnsc_nsrch], DNS_MAXDN) <= 0)
     return errno = EINVAL, -1;
   else
@@ -461,17 +463,17 @@
   int ret = -1;
 
   h_iphlpapi = LoadLibrary("iphlpapi.dll");
-  if (h_iphlpapi == HANDLE_ERROR)
+  if (!h_iphlpapi)
     return -1;
   pfnGetAdAddrs = (GetAdaptersAddressesFunc)
-    GetProcAddress(iphlp, "GetAdaptersAddresses");
+    GetProcAddress(h_iphlpapi, "GetAdaptersAddresses");
   if (!pfnGetAdAddrs) goto freelib;
   ulOutBufLen = 0;
-  dwRetVal = GetAdAddrs(AF_UNSPEC, 0, NULL, NULL, &ulOutBufLen);
+  dwRetVal = pfnGetAdAddrs(AF_UNSPEC, 0, NULL, NULL, &ulOutBufLen);
   if (dwRetVal != ERROR_BUFFER_OVERFLOW) goto freelib;
   pAddrBuf = malloc(ulOutBufLen);
   if (!pAddrBuf) goto freelib;
-  dwRetVal = GetAdAddrs(AF_UNSPEC, 0, NULL, pAddrBuf, &ulOutBufLen);
+  dwRetVal = pfnGetAdAddrs(AF_UNSPEC, 0, NULL, pAddrBuf, &ulOutBufLen);
   if (dwRetVal != ERROR_SUCCESS) goto freemem;
   for (pAddr = pAddrBuf;
        pAddr && ctx->dnsc_nserv <= DNS_MAXSERV;
@@ -507,7 +509,7 @@
   res = RegQueryValueEx(hk, "NameServer", NULL, &type, valBuf, &len);
   if (res != ERROR_SUCCESS || !len || !valBuf[0]) {
     len = sizeof(valBuf) - 1;
-    res = RegQueryValueEx(hk, "DhcpNameServer", &type, valBuf, &len);
+    res = RegQueryValueEx(hk, "DhcpNameServer", NULL, &type, valBuf, &len);
   }
   RegCloseKey(hk);
   if (res != ERROR_SUCCESS || !len || !valBuf[0])
@@ -751,7 +753,7 @@
 void dns_close(struct dns_ctx *ctx) {
   SETCTXINITED(ctx);
   if (ctx->dnsc_udpsock < 0) return;
-  close(ctx->dnsc_udpsock);
+  closesocket(ctx->dnsc_udpsock);
   ctx->dnsc_udpsock = -1;
   free(ctx->dnsc_pbuf);
   ctx->dnsc_pbuf = NULL;
@@ -1039,7 +1041,7 @@
        * remote errors should be ignored (for now anyway).
        */
 #ifdef WIN32
-      if (WSAGetLastError() != WSAEWOULDBLOCK)
+      if (WSAGetLastError() == WSAEWOULDBLOCK)
 #else
       if (errno == EAGAIN)
 #endif
@@ -1250,9 +1252,6 @@
 
 void *dns_resolve(struct dns_ctx *ctx, struct dns_query *q) {
   time_t now;
-#ifdef WIN32
-# warning fixme: poll()/select() on WIN32 (WaitForMultipleObjects?)
-#endif
 #ifdef HAVE_POLL
   struct pollfd pfd;
 #else

Added: udns/tags/upstream/0.0.9pre/udns_rr_naptr.c
===================================================================
--- udns/branches/upstream/trunk/udns_rr_naptr.c	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/tags/upstream/0.0.9pre/udns_rr_naptr.c	2006-12-06 12:57:21 UTC (rev 2991)
@@ -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 at corpit.ru>
+   Copyright (C) 2006  Mikael Magnusson <mikma at users.sourceforge.net>
+   This file is part of UDNS library, an async DNS stub resolver.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library, in file named COPYING.LGPL; if not,
+   write to the Free Software Foundation, Inc., 59 Temple Place,
+   Suite 330, Boston, MA  02111-1307  USA
+
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "udns.h"
+
+/* Get a single string for NAPTR record, pretty much like a DN label.
+ * String length is in first byte in *cur, so it can't be >255.
+ */
+static int dns_getstr(dnscc_t **cur, dnscc_t *ep, char *buf)
+{
+  unsigned l;
+  dnscc_t *cp = *cur;
+
+  l = *cp++;
+  if (cp + l > ep)
+    return DNS_E_PROTOCOL;
+  if (buf) {
+    memcpy(buf, cp, l);
+    buf[l] = '\0';
+  }
+  cp += l;
+
+  *cur = cp;
+  return l + 1;
+}
+
+int
+dns_parse_naptr(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
+                void **result) {
+  struct dns_rr_naptr *ret;
+  struct dns_parse p;
+  struct dns_rr rr;
+  int r, l;
+  char *sp;
+  dnsc_t dn[DNS_MAXDN];
+
+  assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_NAPTR);
+
+  /* first, validate the answer and count size of the result */
+  l = 0;
+  dns_initparse(&p, qdn, pkt, cur, end);
+  while((r = dns_nextrr(&p, &rr)) > 0) {
+    int i;
+    dnscc_t *ep = rr.dnsrr_dend;
+
+    /* first 4 bytes: order & preference */
+    cur = rr.dnsrr_dptr + 4;
+
+    /* flags, services and regexp */
+    for (i = 0; i < 3; i++) {
+      r = dns_getstr(&cur, ep, NULL);
+      if (r < 0)
+        return r;
+      l += r;
+    }
+    /* replacement */
+    r = dns_getdn(pkt, &cur, end, dn, sizeof(dn));
+    if (r <= 0 || cur != rr.dnsrr_dend)
+      return DNS_E_PROTOCOL;
+    l += dns_dntop_size(dn);
+  }
+  if (r < 0)
+    return DNS_E_PROTOCOL;
+  if (!p.dnsp_nrr)
+    return DNS_E_NODATA;
+
+  /* next, allocate and set up result */
+  l += dns_stdrr_size(&p);
+  ret = malloc(sizeof(*ret) + sizeof(struct dns_naptr) * p.dnsp_nrr + l);
+  if (!ret)
+    return DNS_E_NOMEM;
+  ret->dnsnaptr_nrr = p.dnsp_nrr;
+  ret->dnsnaptr_naptr = (struct dns_naptr *)(ret+1);
+
+  /* and 3rd, fill in result, finally */
+  sp = (char*)(&ret->dnsnaptr_naptr[p.dnsp_nrr]);
+  for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r) {
+    cur = rr.dnsrr_dptr;
+    ret->dnsnaptr_naptr[r].order = dns_get16(cur); cur += 2;
+    ret->dnsnaptr_naptr[r].preference = dns_get16(cur); cur += 2;
+    sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].flags = sp));
+    sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].service = sp));
+    sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].regexp = sp));
+    dns_getdn(pkt, &cur, end, dn, sizeof(dn));
+    sp += dns_dntop(dn, (ret->dnsnaptr_naptr[r].replacement = sp), DNS_MAXNAME);
+  }
+  dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p);
+  *result = ret;
+  return 0;
+}
+
+struct dns_query *
+dns_submit_naptr(struct dns_ctx *ctx, const char *name, int flags,
+                 dns_query_naptr_fn *cbck, void *data) {
+  return
+    dns_submit_p(ctx, name, DNS_C_IN, DNS_T_NAPTR, flags,
+                 dns_parse_naptr, (dns_query_fn *)cbck, data);
+}
+
+struct dns_rr_naptr *
+dns_resolve_naptr(struct dns_ctx *ctx, const char *name, int flags) {
+  return (struct dns_rr_naptr *)
+    dns_resolve_p(ctx, name, DNS_C_IN, DNS_T_NAPTR, flags, dns_parse_naptr);
+}


Property changes on: udns/tags/upstream/0.0.9pre/udns_rr_naptr.c
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Modified: udns/tags/upstream/0.0.9pre/udns_rr_txt.c
===================================================================
--- udns/branches/upstream/trunk/udns_rr_txt.c	2006-12-06 12:49:32 UTC (rev 2990)
+++ udns/tags/upstream/0.0.9pre/udns_rr_txt.c	2006-12-06 12:57:21 UTC (rev 2991)
@@ -1,4 +1,4 @@
-/* $Id: udns_rr_txt.c,v 1.14 2005/04/20 06:44:34 mjt Exp $
+/* $Id: udns_rr_txt.c,v 1.15 2006/11/28 22:45:20 mjt Exp $
    parse/query TXT records
 
    Copyright (C) 2005  Michael Tokarev <mjt at corpit.ru>
@@ -78,7 +78,7 @@
     ret->dnstxt_txt[r].len = sp - ret->dnstxt_txt[r].txt;
     *sp++ = '\0';
   }
-  dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p);
+  dns_stdrr_finish((struct dns_rr_null *)ret, (char*)sp, &p);
   *result = ret;
   return 0;
 }



More information about the Minisip-devel mailing list