r2974 - in branches/ppcgui: . ex-libs ex-libs/udns-arm
ex-libs/udns-arm/build ex-libs/udns-arm/win32
ex-libs/udns-arm/win32/_UpgradeReport_Files
athkar at minisip.org
athkar at minisip.org
Wed Nov 29 00:01:42 CET 2006
Author: athkar
Date: 2006-11-29 00:01:41 +0100 (Wed, 29 Nov 2006)
New Revision: 2974
Added:
branches/ppcgui/ex-libs/
branches/ppcgui/ex-libs/udns-arm/
branches/ppcgui/ex-libs/udns-arm/Makefile
branches/ppcgui/ex-libs/udns-arm/TODO
branches/ppcgui/ex-libs/udns-arm/build/
branches/ppcgui/ex-libs/udns-arm/build/dnsget.exe
branches/ppcgui/ex-libs/udns-arm/build/udns.dll
branches/ppcgui/ex-libs/udns-arm/build/udns.lib
branches/ppcgui/ex-libs/udns-arm/dnsget.c
branches/ppcgui/ex-libs/udns-arm/rblcheck.c
branches/ppcgui/ex-libs/udns-arm/readme1st.txt
branches/ppcgui/ex-libs/udns-arm/udns.3
branches/ppcgui/ex-libs/udns-arm/udns.h
branches/ppcgui/ex-libs/udns-arm/udns_bl.c
branches/ppcgui/ex-libs/udns-arm/udns_dn.c
branches/ppcgui/ex-libs/udns-arm/udns_dntosp.c
branches/ppcgui/ex-libs/udns-arm/udns_misc.c
branches/ppcgui/ex-libs/udns-arm/udns_parse.c
branches/ppcgui/ex-libs/udns-arm/udns_resolver.c
branches/ppcgui/ex-libs/udns-arm/udns_rr_a.c
branches/ppcgui/ex-libs/udns-arm/udns_rr_mx.c
branches/ppcgui/ex-libs/udns-arm/udns_rr_ptr.c
branches/ppcgui/ex-libs/udns-arm/udns_rr_txt.c
branches/ppcgui/ex-libs/udns-arm/win32/
branches/ppcgui/ex-libs/udns-arm/win32/UpgradeLog.XML
branches/ppcgui/ex-libs/udns-arm/win32/_UpgradeReport_Files/
branches/ppcgui/ex-libs/udns-arm/win32/_UpgradeReport_Files/Thumbs.db
branches/ppcgui/ex-libs/udns-arm/win32/_UpgradeReport_Files/UpgradeReport.css
branches/ppcgui/ex-libs/udns-arm/win32/_UpgradeReport_Files/UpgradeReport.xslt
branches/ppcgui/ex-libs/udns-arm/win32/_UpgradeReport_Files/UpgradeReport_Minus.gif
branches/ppcgui/ex-libs/udns-arm/win32/_UpgradeReport_Files/UpgradeReport_Plus.gif
branches/ppcgui/ex-libs/udns-arm/win32/dnsget.rc
branches/ppcgui/ex-libs/udns-arm/win32/dnsget.vcproj
branches/ppcgui/ex-libs/udns-arm/win32/dnsget.vcproj.7.10.old
branches/ppcgui/ex-libs/udns-arm/win32/dnsget.vcproj.XPS.thanasis.user
branches/ppcgui/ex-libs/udns-arm/win32/resource.h
branches/ppcgui/ex-libs/udns-arm/win32/udns.aps
branches/ppcgui/ex-libs/udns-arm/win32/udns.rc
branches/ppcgui/ex-libs/udns-arm/win32/udns.sln
branches/ppcgui/ex-libs/udns-arm/win32/udns.sln.old
branches/ppcgui/ex-libs/udns-arm/win32/udns.suo
branches/ppcgui/ex-libs/udns-arm/win32/udns.vcproj
branches/ppcgui/ex-libs/udns-arm/win32/udns.vcproj.7.10.old
branches/ppcgui/ex-libs/udns-arm/win32/udns.vcproj.XPS.thanasis.user
branches/ppcgui/ex-libs/udns-arm/win32/udns_codes.c
branches/ppcgui/ex-libs/udns-arm/win32/win32.c
branches/ppcgui/ex-libs/udns-arm/win32/win32.h
Log:
Upload of the udns pocket pc port (including the dnsget.exe example
Added: branches/ppcgui/ex-libs/udns-arm/Makefile
===================================================================
--- branches/ppcgui/ex-libs/udns-arm/Makefile 2006-11-28 22:30:15 UTC (rev 2973)
+++ branches/ppcgui/ex-libs/udns-arm/Makefile 2006-11-28 23:01:41 UTC (rev 2974)
@@ -0,0 +1,71 @@
+# $Id: Makefile,v 1.18 2004/07/11 11:17:40 mjt Exp $
+# libudns Makefile
+#
+UDNS_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_HDRS = udns.h
+UDNS_GENS = udns_codes.c
+UDNS_UTIL = dnsget.c rblcheck.c
+UDNS_DIST = udns.h udns.3 $(UDNS_SRCS) Makefile TODO $(UDNS_UTIL)
+UDNS_OBJS = $(UDNS_SRCS:.c=.o) $(UDNS_GENS:.c=.o)
+UDNS_NAME = udns
+UDNS_LIBS = lib$(UDNS_NAME).a
+UDNS_VERS = 0.0.4
+
+CFLAGS = -Wall -W -Wmissing-prototypes -DHAVE_POLL
+AWK = awk
+
+all: lib$(UDNS_NAME).a $(UDNS_UTIL:.c=)
+
+lib$(UDNS_NAME).a: $(UDNS_OBJS)
+ -rm -f $@
+ $(AR) rv $@ $(UDNS_OBJS)
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+udns_codes.c: udns.h Makefile
+ @echo Generating $@
+ @set -e; exec >$@.tmp; \
+ set T type C class R rcode; \
+ echo "/* Automatically generated. */"; \
+ echo "#include \"udns.h\""; \
+ echo "#include <stdio.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) }" \
+ $< ; \
+ 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++}\
+ " $< ; \
+ echo " }"; \
+ echo " sprintf(nm,\"$$2%d\", code);"; \
+ echo " return nm;"; \
+ echo "}"; \
+ shift 2; \
+ done
+ @mv $@.tmp $@
+
+$(UDNS_NAME).3.html: $(UDNS_NAME).3
+ groff -man -Thtml $< > $@.tmp
+ mv $@.tmp $@
+
+$(UDNS_OBJS): $(UDNS_HDRS)
+dnsget: dnsget.c $(UDNS_HDRS) lib$(UDNS_NAME).a
+ $(CC) $(CFLAGS) -o $@ $< lib$(UDNS_NAME).a
+rblcheck: rblcheck.c $(UDNS_HDRS) lib$(UDNS_NAME).a
+ $(CC) $(CFLAGS) -o $@ $< lib$(UDNS_NAME).a
+
+dist: $(UDNS_NAME)-$(UDNS_VERS).tar.gz
+$(UDNS_NAME)-$(UDNS_VERS).tar.gz: $(UDNS_DIST)
+ tar cvfz $@ $(UDNS_DIST)
+clean:
+ rm -f $(UDNS_OBJS) $(UDNS_GENS)
+distclean: clean
+ rm -f $(UDNS_LIBS) $(UDNS_NAME).3.html
Added: branches/ppcgui/ex-libs/udns-arm/TODO
===================================================================
--- branches/ppcgui/ex-libs/udns-arm/TODO 2006-11-28 22:30:15 UTC (rev 2973)
+++ branches/ppcgui/ex-libs/udns-arm/TODO 2006-11-28 23:01:41 UTC (rev 2974)
@@ -0,0 +1,52 @@
+$Id: TODO,v 1.7 2004/07/11 11:18:36 mjt Exp $
+
+The following is mostly an internal, not user-visible stuff.
+
+* 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.
+
+* in dns_set_serv() (set list of nameservers to use), we may
+ accept *names* in addition to IP addresses, and perform
+ internal resolving using current (defined) set of nameservers.
+ Is such a feature useful for anything but debugging tools
+ such as dig, host, etc?
+
+* DNS_OPT_FLAGS should be DNS_OPT_ADDFLAGS and DNS_OPT_SETFLAGS.
+ Currently one can't add a single flag bit but preserve
+ existing bits... at least not without retrieving all current
+ flags before, which isn't that bad anyway.
+
+* dns_set_opts() may process flags too (such as aaonly etc)
+
+* a way to disable $NSCACHEIP et al processing?
+
+* initialize/open the context automatically, and be more
+ liberal about initialization in general?
+
+* dns_init(do_open) - make the parameter opposite, aka
+ dns_init(skip_open) ?
+
+* 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.
Added: branches/ppcgui/ex-libs/udns-arm/build/dnsget.exe
===================================================================
(Binary files differ)
Property changes on: branches/ppcgui/ex-libs/udns-arm/build/dnsget.exe
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/ppcgui/ex-libs/udns-arm/build/udns.dll
===================================================================
(Binary files differ)
Property changes on: branches/ppcgui/ex-libs/udns-arm/build/udns.dll
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/ppcgui/ex-libs/udns-arm/build/udns.lib
===================================================================
(Binary files differ)
Property changes on: branches/ppcgui/ex-libs/udns-arm/build/udns.lib
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/ppcgui/ex-libs/udns-arm/dnsget.c
===================================================================
--- branches/ppcgui/ex-libs/udns-arm/dnsget.c 2006-11-28 22:30:15 UTC (rev 2973)
+++ branches/ppcgui/ex-libs/udns-arm/dnsget.c 2006-11-28 23:01:41 UTC (rev 2974)
@@ -0,0 +1,353 @@
+/* $Id: dnsget.c,v 1.3 2004/07/11 10:34:40 mjt Exp $
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef WIN32
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include <time.h>
+#include "udns.h"
+
+static char *progname;
+static int verbose = 1;
+static int errors;
+static int notfound;
+
+static const struct qtype {
+ const char *name;
+ enum dns_type qtyp;
+ int flags;
+} qtypes[] = {
+ { "a", DNS_T_A, 0 },
+ { "aaaa", DNS_T_AAAA, 0 },
+ { "ptr", DNS_T_PTR, 1 },
+ { "mx", DNS_T_MX, 0 },
+ { "txt", DNS_T_TXT, 0 },
+ { 0, 0, 0 }
+};
+
+static const struct qtype *qt;
+static enum dns_class qcls = DNS_C_IN;
+
+static void
+dnserror(const char *name, int errnum) {
+ if (verbose >= 0)
+ fprintf(stderr, "%s: unable to lookup %s record for %s: %s\n",
+ progname, qt->name, name, dns_strerror(errnum));
+ if (errnum == DNS_E_NXDOMAIN || errnum == DNS_E_NODATA)
+ ++notfound;
+ else
+ ++errors;
+}
+
+static void xperr() {
+ printf("<parse error>\n");
+ ++errors;
+}
+
+static int
+printsection(const unsigned char *pkt,
+ const unsigned char **curp,
+ const unsigned char *end,
+ enum dns_class qcls, enum dns_type qtyp,
+ int nrr, const char *name) {
+ unsigned char dn[DNS_MAXDN];
+ enum dns_class cls;
+ enum dns_type typ;
+ unsigned ttl;
+ unsigned dsz;
+ const unsigned char *dptr, *dend, *c, *cur = *curp;
+ int n;
+ if (!nrr) return 0;
+ if (verbose > 1) printf("\n;; %s section (%d):\n", name, nrr);
+
+ while(nrr--) {
+ if (dns_getdn(pkt, &cur, end, dn, sizeof(dn)) <= 0)
+ return -1;
+ if (cur + 10 > end) return -1;
+ typ = dns_get16(cur); cur += 2;
+ cls = dns_get16(cur); cur += 2;
+ ttl = dns_get32(cur); cur += 4;
+ dsz = dns_get16(cur); cur += 2;
+ dptr = cur;
+ dend = cur = cur + dsz;
+ if (cur > end) return -1;
+ if (qcls && cls != qcls) continue;
+ if (qtyp &&
+ (typ != qtyp && (typ != DNS_T_CNAME || verbose <= 0)))
+ continue;
+ if (verbose > 0) {
+ if (verbose > 1) {
+ if (!nrr && !dn[0] && typ == DNS_T_OPT) {
+ printf(";EDNS0 OPT record (UDPsize: %d): %d bytes\n", cls, dsz);
+ continue;
+ }
+ n = printf("%s.", dns_dntosp(dn));
+ printf("%s%u\t%s\t%s\t",
+ n > 15 ? "\t" : n > 7 ? "\t\t" : "\t\t\t",
+ ttl, dns_classname(cls), dns_typename(typ));
+ }
+ else printf("%s. %s ", dns_dntosp(dn), dns_typename(typ));
+ }
+ switch(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, dend, dn, sizeof(dn)) <= 0) {
+ xperr(); continue;
+ }
+ printf("%s.\n", dns_dntosp(dn));
+ break;
+
+ case DNS_T_A:
+ if (dsz != 4) xperr();
+ else printf("%d.%d.%d.%d\n", dptr[0], dptr[1], dptr[2], dptr[3]);
+ break;
+
+ case DNS_T_AAAA:
+ if (dsz != 16) xperr();
+ else printf("%s\n", inet_ntop(AF_INET6, dptr, dn, 16));
+ break;
+
+ case DNS_T_MX:
+ c = dptr + 2;
+ if (dns_getdn(pkt, &c, dend, dn, sizeof(dn)) <= 0) xperr();
+ else printf("%d %s.\n", 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) {
+ xperr();
+ c = 0;
+ break;
+ }
+ }
+ if (!c) continue;
+ c = dptr;
+ if (verbose > 0) {
+ const unsigned char *e;
+ int i = 0;
+ while(c < dend) {
+ n = *c++;
+ e = c + n;
+ printf("%s\"", i++?" ":"");
+ while(c < e) {
+ if (*c < ' ' || *c >= 127) printf("\\%02x", *c);
+ else if (*c == '\\' || *c == '"') printf("\\%c", *c);
+ else putchar(*c);
+ ++c;
+ }
+ putchar('"');
+ }
+ }
+ else {
+ while(c < dend) {
+ n = *c++;
+ fwrite(c, n, 1, stdout);
+ c += n;
+ }
+ }
+ putchar('\n');
+ break;
+
+ case DNS_T_SOA:
+ if (dns_getdn(pkt, &dptr, dend, dn, sizeof(dn)) <= 0) { xperr(); break; }
+ printf("%s. ", dns_dntosp(dn));
+ if (dns_getdn(pkt, &dptr, dend, dn, sizeof(dn)) <= 0) { xperr(); break; }
+ printf("%s. ", dns_dntosp(dn));
+ if (dptr + 4*5 != dend) { xperr(); break; }
+ printf("%u %u %u %u %u\n",
+ dns_get32(dptr), dns_get32(dptr+4), dns_get32(dptr+8),
+ dns_get32(dptr+12), dns_get32(dptr+16));
+ break;
+
+ case DNS_T_MINFO:
+ if (dns_getdn(pkt, &dptr, dend, dn, sizeof(dn)) <= 0) { xperr(); break; }
+ printf("%s. ", dns_dntosp(dn));
+ if (dns_getdn(pkt, &dptr, dend, dn, sizeof(dn)) <= 0) { xperr(); break; }
+ printf("%s.\n", dns_dntosp(dn));
+ break;
+
+ case DNS_T_HINFO:
+ case DNS_T_WKS:
+ case DNS_T_A6:
+ case DNS_T_NULL:
+
+ default:
+ printf("<unknown RR type (size %d)>\n", dsz);
+ break;
+ }
+ }
+ *curp = cur;
+ return 0;
+}
+
+static void dnscb(struct dns_ctx *ctx, void *result, void *data) {
+ int r = dns_status(ctx);
+ const char *name = data;
+ const unsigned char *pkt = result;
+ const unsigned char *end = pkt + r;
+ const unsigned char *cur, *qdn;
+ enum dns_class qcls;
+ enum dns_type qtyp;
+ if (!result) {
+ dnserror(name, r);
+ return;
+ }
+ qdn = dns_payload(pkt);
+ cur = qdn + dns_dnlen(qdn);
+ if (verbose > 1) {
+ printf(";; ->>HEADER<<- opcode: QUERY, status: %s, id: %d, size: %d\n",
+ dns_rcodename(dns_rcode(pkt)), dns_qid(pkt), r);
+ printf(";; flags:");
+ 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");
+ printf("; QUERY: %d, ANSWER: %d, AUTHORITY: %d, ADDITIONAL: %d\n",
+ dns_numqd(pkt), dns_numan(pkt), dns_numns(pkt), dns_numar(pkt));
+ printf("\n;; QUERY SECTION (%d):\n", dns_numqd(pkt));
+ r = printf(";%s.", dns_dntosp(qdn));
+ 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)));
+ qcls = 0; qtyp = 0;
+ }
+ else {
+ qtyp = dns_get16(cur); if (qtyp == DNS_T_ANY) qtyp = 0;
+ qcls = dns_get16(cur+2); if (qcls == DNS_C_ANY) qcls = 0;
+ }
+ cur += 4;
+ r = printsection(pkt, &cur, end, qcls, qtyp, dns_numan(pkt), "ANSWER");
+ if (r < 0 || verbose <= 1) { free(result); return; }
+ if (r == 0)
+ r = printsection(pkt, &cur, end, 0, 0, dns_numns(pkt), "AUTHORITY");
+ if (r == 0)
+ r = printsection(pkt, &cur, end, 0, 0, dns_numar(pkt), "ADDITIONAL");
+ putchar('\n');
+ free(result);
+}
+
+void print_usage(void)
+{
+ fprintf(stdout,
+ "Usage: %s [options] domain_name [domain_name ...]\n"
+ " Options\n"
+ " -h Print this help information\n"
+ " -v Be more verbose\n"
+ " -q Be more quiet\n"
+ " -t <type> DNS record type (e.g. \"A\" or \"AAAA\")\n"
+ " -c <class> DNS class (e.g. \"in\")\n"
+ " -n <nameserver> Add nameserver to server list\n",
+ progname);
+}
+
+int main(int argc, char **argv) {
+ int i;
+ int fd;
+ fd_set fds;
+ struct timeval tv;
+ time_t now;
+ struct qtype qtp;
+
+ if (!(progname = strrchr(argv[0], '/'))) progname = argv[0];
+ else argv[0] = ++progname;
+
+ fprintf(stdout, "UDNS dnsget tool\n");
+ dns_init(0);
+
+ while((i = getopt(argc, argv, "hvqn:t:c:")) != EOF) switch(i) {
+ case 'h':
+ print_usage();
+ return 0;
+ break;
+ case 'v': ++verbose; break;
+ case 'q': --verbose; break;
+ case 'n':
+ dns_add_serv(NULL, optarg);
+ break;
+ case 't':
+#if 0
+ for (i = 0; qtypes[i].name; ++i)
+ if (strcmp(qtypes[i].name, optarg) == 0)
+ break;
+ if (!qtypes[i].name) {
+ fprintf(stderr, "%s: unrecognized query type %s\n", progname, optarg);
+ return 1;
+ }
+ qt = &qtypes[i];
+#else
+ i = dns_findtypename(optarg);
+ if (!i) {
+ fprintf(stderr, "%s: unrecognized query type %s\n", progname, optarg);
+ return 1;
+ }
+ qtp.qtyp = i;
+ qtp.name = optarg;
+ qt = &qtp;
+#endif
+ break;
+ case 'c':
+ if (strcmp(optarg, "in") == 0) qcls = DNS_C_IN;
+ else if (strcmp(optarg, "ch") == 0) qcls = DNS_C_CH;
+ else if (strcmp(optarg, "hs") == 0) qcls = DNS_C_HS;
+ else if (strcmp(optarg, "any") == 0) qcls = DNS_C_ANY;
+ else if (strcmp(optarg, "*") == 0) qcls = DNS_C_ANY;
+ else {
+ fprintf(stderr, "%s: unrecognized class type %s\n", progname, optarg);
+ return 1;
+ }
+ break;
+ default: return 1;
+ }
+
+ argc -= optind; argv += optind;
+ if(!argc)
+ {
+ fprintf(stderr, "%s: argument (domain name) missing\n", progname);
+ print_usage();
+ return 1;
+ }
+
+ fd = dns_open(NULL);
+ if (fd < 0) {
+ fprintf(stderr, "%s: unable to initialize dns library: %m\n", progname);
+ return 1;
+ }
+ now = NULL;//time(NULL);
+ if (!qt) qt = qtypes;
+ for(i = 0; i < argc; ++i) {
+ if (!dns_submit_p(0, argv[i], qcls, qt->qtyp, 0, 0, dnscb, argv[i], now))
+ dnserror(argv[i], dns_status(0));
+ else
+ fprintf(stdout, "Started request for '%s'\n", argv[i]);
+ }
+
+ FD_ZERO(&fds);
+ while((i = dns_timeouts(0, -1, now)) > 0) {
+ FD_SET(fd, &fds);
+ tv.tv_sec = i;
+ tv.tv_usec = 0;
+ i = select(fd+1, &fds, 0, 0, &tv);
+ now = NULL;//time(NULL);
+ if (i > 0) dns_ioevent(0, now);
+ }
+
+ return errors ? 1 : notfound ? 100 : 0;
+}
Added: branches/ppcgui/ex-libs/udns-arm/rblcheck.c
===================================================================
--- branches/ppcgui/ex-libs/udns-arm/rblcheck.c 2006-11-28 22:30:15 UTC (rev 2973)
+++ branches/ppcgui/ex-libs/udns-arm/rblcheck.c 2006-11-28 23:01:41 UTC (rev 2974)
@@ -0,0 +1,282 @@
+/* $Id: rblcheck.c,v 1.4 2004/07/09 01:16:13 mjt Exp $
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include "udns.h"
+
+#ifdef WIN32
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+static const char *version = "udns-rblcheck 0.1";
+static char *progname;
+
+struct rblookup {
+ struct ipcheck *parent;
+ struct in_addr key;
+ const char *zone;
+ struct dns_rr_a4 *addr;
+ struct dns_rr_txt *txt;
+};
+
+struct ipcheck {
+ const char *name;
+ int naddr;
+ int listed;
+ struct rblookup *lookup;
+};
+
+#define notlisted ((void*)1)
+
+static int nzones, nzalloc;
+static const char **zones;
+
+static int do_txt;
+static int stopfirst;
+static int verbose = 1;
+/* verbosity level:
+ * <0 - only bare As/TXTs
+ * 0 - what RBL result
+ * 1(default) - what is listed by RBL: result
+ * 2 - what is[not ]listed by RBL: result, name lookups
+ */
+
+static int listed;
+static int failures;
+
+static time_t now;
+
+static void *ecalloc(int size, int cnt) {
+ void *t = calloc(size, cnt);
+ if (!t) {
+ fprintf(stderr, "%s: out of memory\n", progname);
+ exit(1);
+ }
+ return t;
+}
+
+static void addzone(const char *zone) {
+ if (nzones >= nzalloc) {
+ const char **zs = (const char**)ecalloc(sizeof(char*), (nzalloc += 16));
+ if (zones) {
+ memcpy(zs, zones, nzones * sizeof(char*));
+ free(zones);
+ }
+ zones = zs;
+ }
+ zones[nzones++] = zone;
+}
+
+static void dnserror(struct rblookup *ipl, const char *what) {
+ fprintf(stderr, "%s: unable to %s for %s (%s): %s\n",
+ progname, what, inet_ntoa(ipl->key), ipl->zone,
+ dns_strerror(dns_status(0)));
+ ++failures;
+}
+
+static void display_result(struct ipcheck *ipc) {
+ int j;
+ struct rblookup *l, *le;
+ if (!ipc->naddr) return;
+ for (l = ipc->lookup, le = l + nzones * ipc->naddr; l < le; ++l) {
+ if (!l->addr) continue;
+ if (verbose < 2 && l->addr == notlisted) continue;
+ if (verbose >= 0) {
+ if (ipc->name) printf("%s[%s]", ipc->name, inet_ntoa(l->key));
+ else printf("%s", inet_ntoa(l->key));
+ }
+ if (l->addr == notlisted) {
+ printf(" is NOT listed by %s\n", l->zone);
+ continue;
+ }
+ else if (verbose >= 1)
+ printf(" is listed by %s: ", l->zone);
+ else if (verbose >= 0)
+ printf(" %s ", l->zone);
+ if (verbose >= 1 || !do_txt)
+ for (j = 0; j < l->addr->dnsa4_nrr; ++j)
+ printf("%s%s", j ? " " : "", inet_ntoa(l->addr->dnsa4_addr[j]));
+ if (!do_txt) ;
+ else if (l->txt) {
+ for(j = 0; j < l->txt->dnstxt_nrr; ++j) {
+ unsigned char *t = l->txt->dnstxt_txt[j].txt;
+ unsigned char *e = t + l->txt->dnstxt_txt[j].len;
+ printf("%s\"", verbose > 0 ? "\n\t" : j ? " " : "");
+ while(t < e) {
+ if (*t < ' ' || *t >= 127) printf("\\x%02x", *t);
+ else if (*t == '\\' || *t == '"') printf("\\%c", *t);
+ else putchar(*t);
+ ++t;
+ }
+ putchar('"');
+ }
+ free(l->txt);
+ }
+ else
+ printf("%s<no text available>", verbose > 0 ? "\n\t" : "");
+ free(l->addr);
+ putchar('\n');
+ }
+ free(ipc->lookup);
+}
+
+static void txtcb(struct dns_ctx *ctx, struct dns_rr_txt *r, void *data) {
+ struct rblookup *ipl = data;
+ if (r) {
+ ipl->txt = r;
+ ++ipl->parent->listed;
+ }
+ else if (dns_status(ctx) != DNS_E_NXDOMAIN)
+ dnserror(ipl, "lookup DNSBL TXT record");
+}
+
+static void a4cb(struct dns_ctx *ctx, struct dns_rr_a4 *r, void *data) {
+ struct rblookup *ipl = data;
+ if (r) {
+ ipl->addr = r;
+ ++listed;
+ if (do_txt) {
+ if (dns_submit_a4dnsbl_txt(0, &ipl->key, ipl->zone, txtcb, ipl, now))
+ 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, now))
+ dnserror(rl, "submit DNSBL A query");
+ ++rl;
+ }
+ }
+ return 0;
+}
+
+static void namecb(struct dns_ctx *ctx, struct dns_rr_a4 *rr, void *data) {
+ struct ipcheck *ipc = data;
+ if (rr) {
+ submit_a_queries(ipc, rr->dnsa4_nrr, rr->dnsa4_addr);
+ free(rr);
+ }
+ else
+ fprintf(stderr, "%s: unable to lookup %s: %s\n",
+ progname, ipc->name, dns_strerror(dns_status(ctx)));
+}
+
+static int submit(struct ipcheck *ipc) {
+ struct in_addr addr;
+ if (inet_aton(ipc->name, &addr)) {
+ submit_a_queries(ipc, 1, &addr);
+ ipc->name = NULL;
+ }
+ else if (!dns_submit_a4(0, ipc->name, 0, namecb, ipc, now))
+ fprintf(stderr, "%s: unable to submit name query for %s: %s\n",
+ progname, ipc->name, dns_strerror(dns_status(0)));
+ return 0;
+}
+
+static void waitdns(struct ipcheck *ipc) {
+ struct timeval tv;
+ fd_set fds;
+ int c;
+ int fd = dns_sock(NULL);
+ 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;
+
+ if (!(progname = strrchr(argv[0], '/'))) progname = argv[0];
+ else argv[0] = ++progname;
+
+ while((c = getopt(argc, argv, "hqtvms:cn:")) != EOF) switch(c) {
+ case 's': addzone(optarg); break;
+ case 'c': nzones = 0; break;
+ case 'q': --verbose; break;
+ case 'v': ++verbose; break;
+ case 't': do_txt = 1; break;
+ case 'n': nameserver = optarg; break;
+ case 'm': ++stopfirst; break;
+ case 'h':
+ printf("%s: %s.\n", progname, version);
+ printf("Usage is: %s [options] address..\n", progname);
+ printf(
+"Where options are:\n"
+" -h - print this help and exit\n"
+" -s service - add the service (DNSBL zone) to the serice list\n"
+" -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"
+ );
+ return 0;
+ default:
+ fprintf(stderr, "%s: use `%s -h' for help\n", progname, progname);
+ return 1;
+ }
+
+ if (!nzones) {
+ fprintf(stderr, "%s: no service (zone) list specified (-s option)\n",
+ progname);
+ return 1;
+ }
+
+ if (dns_init(1) < 0) {
+ fprintf(stderr, "%s: unable to initialize DNS library: %s\n",
+ progname, strerror(errno));
+ return 1;
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ now = time(NULL);
+ for (c = 0; c < argc; ++c) {
+ if (c && (verbose > 1 || (verbose == 1 && do_txt))) putchar('\n');
+ ipc.name = argv[c];
+ submit(&ipc);
+ waitdns(&ipc);
+ display_result(&ipc);
+ if (stopfirst > 1 && listed) break;
+ }
+
+ return listed ? 100 : failures ? 2 : 0;
+}
Added: branches/ppcgui/ex-libs/udns-arm/readme1st.txt
===================================================================
--- branches/ppcgui/ex-libs/udns-arm/readme1st.txt 2006-11-28 22:30:15 UTC (rev 2973)
+++ branches/ppcgui/ex-libs/udns-arm/readme1st.txt 2006-11-28 23:01:41 UTC (rev 2974)
@@ -0,0 +1,11 @@
+Before building the dnsget executable, make sure to include the udns.lib file located in the /build folder:
+From Tools -> Options:
+ Select Platform: Pocket PC (ARMV4)
+ Show Directories for: library files
+ Then add the complete path to the udns.lib file.
+You should now be able to compile (F6).
+
+
+---
+28-Nov-2006
+Athanasios Karapantelakis (athkar at kth.se)
\ No newline at end of file
Added: branches/ppcgui/ex-libs/udns-arm/udns.3
===================================================================
--- branches/ppcgui/ex-libs/udns-arm/udns.3 2006-11-28 22:30:15 UTC (rev 2973)
+++ branches/ppcgui/ex-libs/udns-arm/udns.3 2006-11-28 23:01:41 UTC (rev 2974)
@@ -0,0 +1,1147 @@
+.\" $Id: udns.3,v 1.14 2004/07/02 21:52:04 mjt Exp $
+.\" udns library manpage
+.\"
+.TH udns 3 "Jun 2004" "Library Functions"
+
+.SH NAME
+udns \- stub DNS resolver library
+
+.SH SYNOPSYS
+.nf
+#include <udns.h>
+struct \fBdns_ctx\fR;
+struct \fBdns_query\fR;
+extern struct dns_ctx \fBdns_defctx\fR;
+struct dns_ctx *\fIctx\fR;
+typedef void \fBdns_query_fn\fR(\fIctx\fR, void *\fIresult\fR, void *\fIdata\fR);
+typedef int
+\fBdns_parse_fn\fR(const unsigned char *\fIpkt\fR, const unsigned char \fIpkte\fR,
+ void **\fIresultp\fR);
+
+\fBcc\fR ... -l\fBudns\fR
+.fi
+
+.SH DESCRIPTION
+
+.PP
+The DNS library, \fBudns\fR, implements thread\-safe stub DNS resolver
+functionality, which may be used both traditional, syncronous way
+and asyncronously, with application\-supplied event loop.
+
+.PP
+While DNS works with both TCP and UDP, performing UDP query first and
+if the result does not fit in UDP buffer (512 bytes max for original
+DNS protocol), retrying the query over TCP, the library uses UDP only,
+but uses EDNS0 (RFCxxx) extensions which allows larger UDP buffers.
+
+.PP
+The library uses single UDP socket to perform all operations even when
+asking multiple nameservers. This way, it is very simple to use the
+library in asyncronous event\-loop applications: an application should
+add only single socket to the set of filedescriptors it monitors for I/O.
+
+.PP
+The library uses two main objects, \fIresolver context\fR of type
+\fBstruct\ dns_ctx\fR, and \fIquery structure\fR of type
+\fBstruct\ dns_query\fR, both are opaque for an application.
+Resolver context holds global information about the resolver,
+such as list of nameservers to use, list of active requests and the like.
+Query objects holds information about a single DNS query in progress and
+are allocated/processed/freed by the library. Pointer to query structure
+may be treated as an identifier of an in\-progress query and may be used
+to cancel the asyncronous query or to wait for it to complete.
+
+.PP
+Asyncronous interface works as follows. An application initializes
+resolver context, submits any number of queries for it using one of
+supplied \fBdns_submit_\fIXXX\fR() routines (each return the query
+identifier as pointer to query structure), waits for input on the
+UDP socket used by the library, and gives some control to the library
+by calling \fBdns_ioevent\fR() and \fBdns_timeouts\fR() routines when
+appropriate. The library performs all necessary processing and executes
+application supplied callback routine when a query completes (either
+successefully or not), giving it the result if any, pointer to the
+resolver context (from which completion status may be obtained), and
+the data pointer supplied by an application when the query has been
+submitted. When submitting a query, an application requests how to
+handle the reply \-\- to either return raw DNS reply packet for its
+own low\-level processing, or it may provide an address of \fIparsing
+routine\fR of type \fBdns_parse_fn\fR to perform conversion of on\-wire
+format into easy to use data structure (the library provides parsing
+routines for several commonly used resource record types, as well as
+type\-safe higher\-level inteface that requests parsing automatically).
+The I/O monitoring and timeout handling may be either traditional
+select() or poll() based, or any callback\-driven technique may be
+used.
+
+.PP
+Additionally, the library provides traditional syncronous interface,
+which may be intermixed with asyncronous calls (during syncronous
+query processing, other asyncronous queries for the same resolver
+context continued to be processed as usual). An application uses
+one of numerous \fBdns_resolve_\fIXXX\fR() routines provided by the
+library to perform a query. As with asyncronous interface, an
+application may either request to return raw DNS packet or type\-specific
+data structure by providing the parsing routine to handle the reply.
+Every routine from \fBdns_resolve_\fIXXX\fR() series return pointer
+to result or NULL in case of any error. Query completion status
+(or length of the raw DNS packet) is available from the resolver
+context using \fBdns_status\fR() routine, the same way as for the
+asyncronous interface.
+
+.PP
+Internally, library uses on\-wire format of domain names, referred
+to as \fIDN format\fR in this manual page. This is a series of domain
+\fIlabels\fR whith preceeding length byte, terminated by zero\-length
+label wich is integral part of the DN format. There are several routines
+provided to convert from traditional asciiz string to DN and back.
+Higher\-level type\-specific query interface hides the DN format from
+an application.
+
+.SH "COMMON DEFINITIONS"
+
+.PP
+Every DNS Resource Record (RR) has a \fItype\fR and a \fIclass\fR.
+The library defines several integer constants, \fBDNS_C_\fIXXX\fR and
+\fBDNS_T_\fIXXX\fR, to use as symbolic names for RR classes and types,
+such as \fBDNS_C_IN\fR for Internet class, \fBDNS_T_A\fR for IPv4
+address record type and so on. See udns.h header file for complete list
+of all such constants.
+
+.PP
+The following constants are defined in dns.h header file:
+.IP "\fBDNS_MAXDN\fR (255 bytes)"
+Maximum length of the domain name in internal (on\-wire) DN format.
+.IP "\fBDNS_MAXLABEL\fR (63 bytes)"
+Maximum length of a single label in DN format.
+.IP "\fBDNS_MAXNAME\fR (1024 bytes)"
+Maximum length of asciiz format of a domain name.
+.IP "\fBDNS_HSIZE\fR (12 bytes)"
+Size of header in DNS packet.
+.IP "\fBDNS_PORT\fR (53)"
+Default port to use when contacting a DNS server.
+.IP "\fBDNS_MAXSERV\fR (6 servers)"
+Maximum number of DNS servers to use.
+.IP "\fBDNS_MAXSRCH\fR (5 search list entries)"
+Maximum number of domain search list
+.IP "\fBDNS_MAXPACKET\fR (512 bytes)"
+Maximum length of DNS UDP packet as specified by original DNS protocol
+.IP "\fBDNS_EDNS0PACKET\fR (4096 bytes)"
+Default length of DNS UDP packet (with EDNS0 extensions) the library uses.
+Note that recursive nameservers usually resides near the client asking them
+to resolve names, e.g. on the same LAN segment or even on the same host, so
+UDP packet fragmentation isn't a problem in most cases. Note also that
+the size of actual packets will be as many bytes as actual reply size requires,
+which is smaller than this value in almost all cases.
+
+.PP
+Additionally, several constants are defined to simplify work with raw DNS
+packets, such as DNS response codes (\fBDNS_R_\fIXXX\fR), DNS header layout
+(\fBDNS_H_\fIXXX\fR) and others. Again, see udns.h for complete list.
+Library error codes (\fBDNS_E_\fIXXX\fR) are described later in this
+manual page.
+
+.SH "RESOLVER CONTEXT"
+
+.PP
+Resolver context, of type \fBstruct\ dns_ctx\fR, is an object which is
+opaque to an application. Several routines provided by the library
+to initialize, copy and free resolver contexts. Most other high\-level
+routines in this library expects a pointer to resolver context, \fIctx\fR,
+as the first argument. There is a default resolver context available,
+named \fBdns_defctx\fR. When the context pointer \fIctx\fR passed to
+a routine is NULL, \fBdns_defctx\fR is used. Several resolver contexts
+may be active at the same time, for example, when an application is
+multi\-threaded and each thread uses resolver.
+.PP
+When initializing resolver context, the library uses information from
+system file /etc/resolv.conf (see \fBresolv.conf\fR(5)), consults
+environment variables \fB$LOCALDOMAIN\fR, \fB$DNSCACHEIP\fR,
+\fB$NAMESERVERS\fR and \fB$RES_OPTIONS\fR, and local host name to obtain
+list of local nameservers, domain name search list and various resolver
+options.
+.PP
+The following routines to initialize resolver context are available:
+.PP
+.nf
+int \fBdns_init\fR(int \fIdo_open\fR)
+struct dns_ctx *\fBdns_new\fR(struct dns_ctx *\fIcopy\fR)
+void \fBdns_free\fR(\fIctx\fR)
+.fi
+.RS
+\fBdns_init\fR() initializes default resolver context, \fBdns_defctx\fR,
+and optionally opens it (if \fIdo_open\fR is true) using \fBdns_open\fR(),
+returning negative value on error.
+\fBdns_new\fR() makes a copy of a given resolver context \fIcopy\fR, or
+default context if \fIcopy\fR is NULL, and returns pointer to it.
+\fBdns_new\fR() may fail if there's no memory available to make a copy
+of \fIcopy\fR, in which case the routine will return NULL pointer.
+\fBdns_free\fR() is used to close assotiated socket and free resolver
+context resources and cancelling (abandoming) all active queries
+assotiated with it. It's ok to free \fBdns_defctx\fR as well as
+dynamically allocated contexts returned by \fBdns_new\fR().
+.RE
+.PP
+.nf
+int \fBdns_set_serv\fR(\fIctx\fR, const char *\fIserv\fR[])
+int \fBdns_set_srch\fR(\fIctx\fR, const char *\fIsrch\fR[])
+.fi
+.RS
+Set the list of nameservers (\fBdns_set_serv\fR()) and search list
+(\fBdns_set_srch\fR()) for the given context \fIctx\fR. Both
+\fIsrv\fR and \fIsrch\fR is an argv\-style list of strings, holding
+IP addresses of nameservers to use and domain names in search list.
+Current values in \fIctx\fR are replaced with the given ones. It is
+an error to call either of this functions if there's at least one
+query is queued for \fIctx\fR.
+.RE
+.PP
+.nf
+int \fBdns_set_opts\fR(\fIctx\fR, const char *\fIopts\fR)
+.fi
+.RS
+set resolver context options from \fIopts\fR string, in the same way as
+processing \fBoptions\fR statement in resolv.conf and \fB$RES_OPTIONS\fR
+environment variable.
+.RE
+.PP
+.nf
+void \fBdns_set_opt\fR(\fIctx\fR, int \fIopt\fR, \fIval\fR)
+.fi
+.RS
+.B TODO
+The \fIflags\fR argument is a bitmask with the following bits defined:
+.IP \fBDNS_NOSRCH\fR
+do not perform domain name search in search list.
+.IP \fBDNS_NORD\fR
+do not request recursion when performing queries
+(i.e. don't set RD flag in querues).
+.IP \fBDNS_AAONLY\fR
+request authoritative answers only (i.e. set AA
+flag in queries).
+.RE
+
+.PP
+.nf
+int \fBdns_open\fR(\fIctx\fR)
+int \fBdns_sock\fR(const \fIctx\fR)
+void \fBdns_close\fR(\fIctx\fR)
+.fi
+.RS
+\fBdns_open\fR() opens the UDP socket used for queries if not already
+open, and return assotiated filedescriptor (or negative value in case
+of error).
+\fBdns_sock\fR() return the UDP socket if open, or -1 if not.
+\fBdns_close\fR() closes the UDP socket if it was open.
+.RE
+
+.PP
+.nf
+int \fBdns_active\fR(const \fIctx\fR)
+.fi
+.RS
+return true if there's at least one query queued for the given context
+\fIctx\fR.
+.RE
+
+.PP
+.nf
+int \fBdns_status\fR(const \fIctx\fR)
+.fi
+.RS
+return status code from last operation. When using syncronous
+interface, this is the query completion status of the last query.
+With asyncronous interface, from within the callback routine,
+this is the query completion status of the query for which the
+callback is being called. When query submission fails, this
+is the error code indicating failure reason. All error codes
+are negative and are represented by \fBDNS_E_\fIXXX\fR constants
+described below.
+.RE
+
+.PP
+.nf
+void \fBdns_ioevent\fR(\fIctx\fR, time_t \fInow\fR)
+.fi
+.RS
+this routine may be called by an application to process I/O
+events on the UDP socket used by the library, as returned
+by \fBdns_sock\fR(). The routine tries to receive incoming
+UDP datagram from the socket and process it. The socket is
+set up to be non\-blocking, so it is safe to call the routine
+even if there's no data to read. The routine will process
+as many datagrams as are queued for the socket, so it is
+safe to use it with either level\-triggered or edge\-triggered
+I/O monitoring model. The \fInow\fR argument is either a
+current time as returned by \fBtime\fR(), or 0, in which
+case the routine will obtain current time by it's own.
+.RE
+
+.PP
+.nf
+int \fBdns_timeouts\fR(\fIctx\fR, int \fImaxwait\fR, time_t \fInow\fR)
+.fi
+.RS
+process any pending timeouts and return number of secounds
+from current time (\fInow\fR if it is not 0) to the time when
+the library wants the application to pass it control to process
+more queued requests. In case when there are no requests pending,
+this time is -1. The routine will not request a time larger than
+\fImaxwait\fR secounds if it is greather or equal to zero. If
+\fInow\fR is 0, the routine will obtain current time by it's own;
+when it is not 0, it should contain current time as returned by
+\fBtime\fR().
+.RE
+
+.PP
+.nf
+typedef int \fBdns_utm_fn\fR(void *\fIarg\fR, struct dns_query *\fIq\fR, int \fItimeout\fR)
+void \fBdns_set_cbck\fR(\fIctx\fR, dns_utm_fn *\fIutmfn\fR, void *\fIarg\fR)
+.fi
+.RS
+An application may use custom callback\-based I/O multiplexing mechanism.
+Usually such a mechanism have concept of a \fItimer\fR, and an ability
+to register a timer event in a form of a callback routine which will
+be executed after certain amount of time. In order to use such an
+event mechanism, udns provides an ability to register and de\-register
+timer events necessary for internal processing using whatever event
+mechanism an application uses. For this to work, it is possible to
+assotiate a pointer to a routine that will perform necessary work for
+(de)registering timer events with a given resolver context, and
+udns will call that routine at appropriate times. Prototype of
+such a routine is shown by \fBdns_utm_fn\fR typedef above. Libudns
+assotiates timers with queue structure only, and there may be only
+one active timer for any given queue structure. To register timer
+event, udns will call the routine giving it the query structure
+in question and non\-zero \fItimeout\fR argument. When a timer is
+not needed anymore, udns de\-registers it by calling the same
+routine with zero \fItimeout\fR. When a timer expires, an application
+should de\-register timer event and call \fBdns_tmevent\fR() routine
+with the query structure as an argument.
+Other, non\-callback timer usage is provided too, see below.
+.RE
+
+.PP
+.nf
+void \fBdns_tmevent\fR(struct dns_query *\fIq\fR, time_t \fInow\fR);
+.fi
+.RS
+routine which should be called from event\-driven application
+event loop when a timer set using routine set up by
+\fBdns_set_cbck\fR() expires.
+.RE
+
+.PP
+.B XXXX TODO: some more resolver context routines, like dns_set_dbgfn() etc.
+
+.SH "QUERY INTERFACE"
+
+.PP
+There are two ways to perform DNS queries: traditional syncronous
+way, when udns performs all the necessary processing and return
+control to the application only when the query completes, and
+asyncronous way, when an application submits one or more queries
+to the library using given resolver context, and waits for completion
+by monitoring filedescriptor used by library and calling library
+routines to process input on that filedescriptor. Asyncronous mode
+works with callback routines: an application supplies an address of
+a routine to execute when the query completes, and a data pointer,
+which is passed to the callback routine.
+
+.PP
+Queries are submitted to the library in a form of \fBstruct\ dns_query\fR.
+To perform asyncronous query, an application allocates memory for the
+\fIquery structure\fR and passes it to the library using \fBdns_submit\fR()
+routines, together with all the query parameters. When the query completes,
+library will call application\-supplied callback routine, giving it the
+resolver context (wich holds query completion status), dynamically allocated
+result (which will be either raw DNS packet or, if applicatin requested parsing
+the result by specifying non-NULL parse routine, ready\-to\-use type\-specific
+structure), and a data pointer provided by an application when it submitted the
+query. It is the application who's responsible for freeing the result memory.
+.PP
+Generic query callback routine looks like this:
+.nf
+typedef void
+\fBdns_query_fn\fR(\fIctx\fR, void *\fIresult\fR, void *\fIdata\fR)
+.fi
+Type\-specific query interface expects similar form of callback
+routine with the only difference in type of \fBresult\fR argument,
+which will be pointer to specific data structure (decoded reply)
+instead of this void pointer to raw DNS packet data.
+
+.PP
+Result parsing routine looks like this:
+.nf
+typedef int
+\fBdns_parse_fn\fR(const unsigned char *\fIpkt\fR, const unsigned char *\fIpkte\fR,
+ void **\fIresultp\fR);
+.fi
+Type\-specific query inteface supplies necessary parsing routines
+automatically.
+
+.PP
+In case of error, query completion status as returned by
+\fBdns_status\fR(\fIctx\fR), will contain one of the following values:
+.IP "positive value"
+length of raw DNS packet if parsing is not requested.
+.IP 0
+the query was successeful and the \fIreply\fR points to type\-specific
+data structure.
+.IP \fBDNS_E_TEMPFAIL\fR
+temporary error, the resolver nameserver was not able to
+process our query or timed out.
+.IP \fBDNS_E_PROTOCOL\fR
+protocol error, a nameserver returned malformed reply.
+.IP \fBDNS_E_NXDOMAIN\fR
+the domain name does not exist.
+.IP \fBDNS_E_NODATA\fR
+there is no data of requested type found.
+.IP \fBDNS_E_NOMEM\fR
+out of memory while processing request.
+.IP \fBDNS_E_BADQUERY\fR
+some aspect of the query (most common is the domain name in question)
+is invalid, and the library can't even start a query.
+
+.PP
+Library provides two series of routines which uses similar interface \-\-
+one for asyncronous queries and another for syncronous queries. There
+are two general low\-level routines in each series to submit (asyncronous
+interface) and resolve (syncronous interface) queries, as well as several
+type\-specific routines with more easy\-to\-use interfaces. To submit
+an asyncronous query, use one of \fBdns_submit_\fIXXX\fR() routine, each
+of which accepts query parameters, pointers to callback routine and to
+callback data, and optional current time hint. Note type\-specific
+\fBdns_submit_\fIXXX\fR() routines expects specific type of the callback
+routine as well, which accepts reply as a pointer to corresponding
+structure, not a void pointer). Every \fBdns_submit_\fIXXX\fR() routine
+return pointer to internal query structure of type struct\ dns_query,
+used as an identifier for the given query.
+
+.PP
+To resolve a query syncronously, use one of \fBdns_resolve_\fIXXX\fR()
+routines, which accepts the same query parameters (but not the
+callback pointers) as corresponding \fBdns_submit_\fIXXX\fR(), and
+return the query result, which is the same as passed to the callback
+routine in case of asyncronous interface.
+
+.PP
+In either case, the result memory (if the query completed successefully)
+is dynamically allocated and should be freed by an application. If
+the query failed for any reason, the result will be NULL, and error
+status will be available from \fBdns_status\fR(\fIctx\fR) routine
+as shown above.
+
+.PP
+.nf
+struct dns_query *
+\fBdns_submit_dn\fR(\fIctx\fR,
+ const unsigned char *\fIdn\fR, \fIqcls\fR, \fIqtyp\fR, \fIflags\fR,
+ \fIparse\fR, \fIcbck\fR, \fIdata\fR, \fInow\fR)
+struct dns_query *
+\fBdns_submit_p\fR(\fIctx\fR,
+ const char *\fIname\fR, \fIqcls\fR, \fIqtyp\fR, \fIflags\fR,
+ \fIparse\fR, \fIcbck\fR, \fIdata\fR, \fInow\fR)
+ enum dns_class \fIqcls\fR;
+ enum dns_type \fIqtyp\fR;
+ int \fIflags\fR;
+ dns_parse_fn *\fIparse\fR;
+ dns_query_fn *\fIcbck\fR;
+ void *\fIdata\fR;
+ time_t \fInow\fR;
+.fi
+.RS
+submit a query for processing for the given resolver context \fIctx\fR.
+Two routines differs only in 3rd argument, which is domain name in
+DN format (\fIdn\fR) or asciiz string (\fIname\fR). The query will be
+performed for the given domain name, with type \fIqtyp\fR in class \fIqcls\fR,
+using option bits in \fIflags\fR, using RR parsing routine pointed by
+\fIparse\fR if not-NULL, and upon completion, \fIcbck\fR function will
+be called with the \fIdata\fR argument. The \fInow\fR argument specifies
+current time as returned by \fBtime\fR() routine, used to minimize number
+of system calls performed by an application; if \fInow\fR is 0, the routine
+will obtain current time by it's own. In case of successeful query submission,
+the routine return pointer to internal query structure which may be treated
+as an identifier of the query as used by the library, and may be used as an
+argument for \fBdns_cancel\fR() routine. In case of error, NULL will be
+returned, and context error status (available using \fIdns_status\fR() routine)
+will be set to corresponding error code, which in this case may be
+DNS_E_BADQUERY if the \fIname\fR of \fIdn\fR is invalid, DNS_E_NOMEM if
+there's no memory available to allocate query structure, or DNS_E_TEMPFAIL
+if an internal error occured.
+.RE
+
+.PP
+.nf
+void *\fBdns_resolve_dn\fR(\fIctx\fR,
+ const unsigned char *\fIdn\fR, \fIqcls\fR, \fIqtyp\fR, \fIflags\fR, \fIparse\fR);
+void *\fBdns_resolve_p\fR(\fIctx\fR,
+ const char *\fIname\fR, \fIqcls\fR, \fIqtyp\fR, \fIflags\fR, \fIparse\fR)
+ \fIparse\fR, \fIcbck\fR, \fIdata\fR, \fInow\fR)
+ enum dns_class \fIqcls\fR;
+ enum dns_type \fIqtyp\fR;
+ int \fIflags\fR;
+ dns_parse_fn *\fIparse\fR;
+.fi
+.RS
+syncronous interface. The routines perform all the steps necessary to resolve
+the given query and return the result. If there's no positive result for any
+reason, all the routines return NULL, and set context error status (available
+using \fBdns_status\fR() routine) to indicate the error code. If the query
+was successeful, context status code will contain either the length of the
+raw DNS reply packet if \fIparse\fR argument was NULL (in which case the return
+value is pointer to the reply DNS packet), or 0 (in which case the return value
+is the result of \fIparse\fR routine). If the query successeful (return value
+is not NULL), the memory returned was dynamically allocated by the library
+and should be free()d by application after use.
+.RE
+
+.PP
+.nf
+void *\fBdns_resolve\fR(\fIctx\fR, struct dns_query *\fIq\fR)
+.fi
+.RS
+wait for the given query \fIq\fR, as returned by one of
+\fBdns_submit_\fIXXX\fR() routines, for completion, and
+return the result. The callback routine will not be called
+for this query. After completion, the query identifier \fIq\fI
+is not valid. Both \fBdns_resolve_dn\fR() and \fBdns_resolve_p\fR()
+are just wrappers around corresponding submit routines and this
+\fBdns_resolve\fR() routine.
+.RE
+
+.PP
+.nf
+void \fBdns_cancel\fR(\fIctx\fR, struct dns_query *\fIq\fR)
+.fi
+.RS
+cancel an active query \fIq\fR, without calling a callback routine.
+After completion, the query identifier \fIq\fR is not valid.
+.RE
+
+.SH "TYPE\-SPECIFIC QUERIES"
+
+.PP
+In addition to the generic low\-level query interface, the library provides
+a set of routines to perform specific queries in a type\-safe manner, as
+well as parsers for several well\-known resource record types. The library
+implements high\-level interface for A, AAAA, PTR, MX and TXT records
+and DNSBL and RHSBL functionality. These routines returns specific types
+as result of a query, instead of raw DNS packets. The following types
+and routines are available.
+
+.PP
+.nf
+struct \fBdns_rr_null\fR {
+ char *\fBdnsn_qname\fR; /* original query name */
+ char *\fBdnsn_cname\fR; /* canonical name */
+ unsigned \fBdnsn_ttl\fR; /* Time\-To\-Live (TTL) value */
+ int \fBdnsn_nrr\fR; /* number of records in the set */
+};
+.fi
+.PP
+NULL RR set, used as a base for all other RR type structures.
+Every RR structure as used by the library have four standard
+fields as in struct\ \fBdns_rr_null\fR.
+
+.SS "IN A Queries"
+.PP
+.nf
+struct \fBdns_rr_a4\fR { /* IN A RRset */
+ char *\fBdnsa4_qname\fR; /* original query name */
+ char *\fBdnsa4_cname\fR; /* canonical name */
+ unsigned \fBdnsa4_ttl\fR; /* Time\-To\-Live (TTL) value */
+ int \fBdnsa4_nrr\fR; /* number of addresses in the set */
+ struct in_addr \fBdnsa4_addr\fR[]; /* array of addresses */
+};
+typedef void
+ \fBdns_query_a4_fn\fR(\fIctx\fR, struct dns_rr_a4 *\fIresult\fR, \fIdata\fR)
+dns_parse_fn \fBdns_parse_a4\fB;
+struct dns_query *
+\fBdns_submit_a4\fB(\fIctx\fR, const char \fIname\fR, int \fIflags\fR,
+ dns_query_a4_fn *\fIcbck\fR, \fIdata\fR, \fInow\fR);
+struct dns_rr_a4 *
+\fBdns_resolve_a4\fB(\fIctx\fR, const char \fIname\fR, int \fIflags\fR);
+.fi
+.PP
+The \fBstruct\ dns_rr_a4\fR structure holds a result of an \fBIN A\fR query,
+which is an array of IPv4 addresses. Callback routine for IN A queries
+expected to be of type \fBdns_query_a4_fn\fR, which expects pointer to
+struct\ \fBdns_rr_a4\fR structure as query result instead of raw DNS packet.
+The \fBdns_parse_a4\fR() is used to convert raw DNS reply packet into
+struct\ \fBdns_rr_a4\fR (it is used internally and may be used directly too
+with generic query interface). Routines \fBdns_submit_a4\fR() and
+\fBdns_resolve_a4\fR() are used to perform A IN queries in a type\-safe
+manner. The \fIname\fR parameter is the domain name in question, and
+\fIflags\fR is query flags bitmask, with one bit, DNS_NOSRCH, of practical
+interest (if the \fIname\fR is absolute, that is, it ends up with a dot,
+DNS_NOSRCH flag will be set automatically).
+
+.SS "IN AAAA Queries"
+.PP
+.nf
+struct \fBdns_rr_a6\fR { /* IN AAAA RRset */
+ char *\fBdnsa6_qname\fR; /* original query name */
+ char *\fBdnsa6_cname\fR; /* canonical name */
+ unsigned \fBdnsa6_ttl\fR; /* Time\-To\-Live (TTL) value */
+ int \fBdnsa6_nrr\fR; /* number of addresses in the set */
+ struct in6_addr \fBdnsa6_addr\fR[]; /* array of addresses */
+};
+typedef void
+ \fBdns_query_a6_fn\fR(\fIctx\fR, struct dns_rr_a6 *\fIresult\fR, \fIdata\fR)
+dns_parse_fn \fBdns_parse_a6\fB;
+struct dns_query *
+\fBdns_submit_a6\fB(\fIctx\fR, const char \fIname\fR, int \fIflags\fR,
+ dns_query_a6_fn *\fIcbck\fR, \fIdata\fR, \fInow\fR);
+struct dns_rr_a6 *
+\fBdns_resolve_a6\fB(\fIctx\fR, const char \fIname\fR, int \fIflags\fR);
+.fi
+.PP
+The \fBstruct\ dns_rr_a6\fR structure holds a result of an \fBIN AAAA\fR query,
+which is an array of IPv6 addresses. Callback routine for IN AAAA queries
+expected to be of type \fBdns_query_a6_fn\fR, which expects pointer to
+struct\ \fBdns_rr_a6\fR structure as query result instead of raw DNS packet.
+The \fBdns_parse_a6\fR() is used to convert raw DNS reply packet into
+struct\ \fBdns_rr_a6\fR (it is used internally and may be used directly too
+with generic query interface). Routines \fBdns_submit_a6\fR() and
+\fBdns_resolve_a6\fR() are used to perform AAAA IN queries in a type\-safe
+manner. The \fIname\fR parameter is the domain name in question, and
+\fIflags\fR is query flags bitmask, with one bit, DNS_NOSRCH, of practical
+interest (if the \fIname\fR is absolute, that is, it ends up with a dot,
+DNS_NOSRCH flag will be set automatically).
+
+.SS "IN PTR Queries"
+.PP
+.nf
+struct \fBdns_rr_ptr\fR { /* IN PTR RRset */
+ char *\fBdnsptr_qname\fR; /* original query name */
+ char *\fBdnsptr_cname\fR; /* canonical name */
+ unsigned \fBdnsptr_ttl\fR; /* Time\-To\-Live (TTL) value */
+ int \fBdnsptr_nrr\fR; /* number of domain name pointers */
+ char *\fBdnsptr_ptr\fR[]; /* array of domain name pointers */
+};
+typedef void
+ \fBdns_query_ptr_fn\fR(\fIctx\fR, struct dns_rr_ptr *\fIresult\fR, \fIdata\fR)
+dns_parse_fn \fBdns_parse_ptr\fB;
+struct dns_query *
+\fBdns_submit_a4ptr\fB(\fIctx\fR, const struct in_addr *\fBaddr\fR,
+ dns_query_ptr_fn *\fIcbck\fR, \fIdata\fR, \fInow\fR);
+struct dns_rr_ptr *
+\fBdns_resolve_a4ptr\fB(\fIctx\fR, const struct in_addr *\fBaddr\fR);
+struct dns_query *
+\fBdns_submit_a6ptr\fB(\fIctx\fR, const struct in6_addr *\fBaddr\fR,
+ dns_query_ptr_fn *\fIcbck\fR, \fIdata\fR, \fInow\fR);
+struct dns_rr_ptr *
+\fBdns_resolve_a6ptr\fB(\fIctx\fR, const struct in6_addr *\fBaddr\fR);
+.fi
+.PP
+The \fBstruct\ dns_rr_ptr\fR structure holds a result of an IN PTR query, which
+is an array of domain name pointers for a given IPv4 or IPv6 address.
+Callback routine for IN PTR queries expected to be of type
+\fBdns_query_ptr_fn\fR, which expects pointer to struct\ \fBdns_rr_ptr\fR
+structure as query result instead of raw DNS packet. The \fBdns_parse_ptr\fR()
+is used to convert raw DNS reply packet into struct\ \fBdns_rr_ptr\fR
+(it is used internally and may be used directly too with generic query
+interface). Routines \fBdns_submit_a4ptr\fR() and \fBdns_resolve_a4ptr\fR()
+are used to perform IN PTR queries for IPv4 addresses in a type\-safe
+manner. Routines \fBdns_submit_a6ptr\fR() and \fBdns_resolve_a6ptr\fR()
+are used to perform IN PTR queries for IPv6 addresses.
+
+.SS "IN MX Queries"
+.PP
+.nf
+struct \fBdns_mx\fR { /* single MX record */
+ int \fBpriority\fR; /* priority value of this MX */
+ char *\fBname\fR; /* domain name of this MX */
+};
+struct \fBdns_rr_mx\fR { /* IN MX RRset */
+ char *\fBdnsmx_qname\fR; /* original query name */
+ char *\fBdnsmx_cname\fR; /* canonical name */
+ unsigned \fBdnsmx_ttl\fR; /* Time\-To\-Live (TTL) value */
+ int \fBdnsmx_nrr\fR; /* number of mail exchangers in the set */
+ struct dns_mx \fBdnsmx_mx\fR[]; /* array of mail exchangers */
+};
+typedef void
+ \fBdns_query_mx_fn\fR(\fIctx\fR, struct dns_rr_mx *\fIresult\fR, \fIdata\fR)
+dns_parse_fn \fBdns_parse_mx\fB;
+struct dns_query *
+\fBdns_submit_mx\fB(\fIctx\fR, const char \fIname\fR, int \fIflags\fR,
+ dns_query_mx_fn *\fIcbck\fR, \fIdata\fR, \fInow\fR);
+struct dns_rr_mx *
+\fBdns_resolve_mx\fB(\fIctx\fR, const char \fIname\fR, int \fIflags\fR);
+.fi
+.PP
+The \fBstruct\ dns_rr_mx\fR structure holds a result of an IN MX query, which
+is an array of mail exchangers for a given domain. Callback routine for IN MX
+queries expected to be of type \fBdns_query_mx_fn\fR, which expects pointer to
+struct\ \fBdns_rr_mx\fR structure as query result instead of raw DNS packet.
+The \fBdns_parse_mx\fR() is used to convert raw DNS reply packet into
+struct\ \fBdns_rr_mx\fR (it is used internally and may be used directly too
+with generic query interface). Routines \fBdns_submit_mx\fR() and
+\fBdns_resolve_mx\fR() are used to perform IN MX queries in a type\-safe
+manner. The \fIname\fR parameter is the domain name in question, and
+\fIflags\fR is query flags bitmask, with one bit, DNS_NOSRCH, of practical
+interest (if the \fIname\fR is absolute, that is, it ends up with a dot,
+DNS_NOSRCH flag will be set automatically).
+
+.SS "TXT Queries"
+.PP
+.nf
+struct \fBdns_txt\fR { /* single TXT record */
+ int \fBlen\fR; /* length of the text */
+ unsigned char *\fBtxt\fR; /* pointer to the text */
+};
+struct \fBdns_rr_txt\fR { /* TXT RRset */
+ char *\fBdnstxt_qname\fR; /* original query name */
+ char *\fBdnstxt_cname\fR; /* canonical name */
+ unsigned \fBdnstxt_ttl\fR; /* Time\-To\-Live (TTL) value */
+ int \fBdnstxt_nrr\fR; /* number of text records in the set */
+ struct dns_txt \fBdnstxt_txt\fR[]; /* array of mail exchangers */
+};
+typedef void
+ \fBdns_query_txt_fn\fR(\fIctx\fR, struct dns_rr_txt *\fIresult\fR, \fIdata\fR)
+dns_parse_fn \fBdns_parse_txt\fB;
+struct dns_query *
+\fBdns_submit_txt\fB(\fIctx\fR, const char \fIname\fR, enum dns_class \fIqcls\fR,
+ int \fIflags\fR, dns_query_txt_fn *\fIcbck\fR, \fIdata\fR, \fInow\fR);
+struct dns_rr_txt *
+\fBdns_resolve_txt\fB(\fIctx\fR, const char \fIname\fR,
+ enum dns_class \fIqcls\fR, int \fIflags\fR);
+.fi
+.PP
+The \fBstruct\ dns_rr_txt\fR structure holds a result of an IN MX query, which
+is an array of mail exchangers for a given domain. Callback routine for IN MX
+queries expected to be of type \fBdns_query_txt_fn\fR, which expects pointer to
+struct\ \fBdns_rr_txt\fR structure as query result instead of raw DNS packet.
+The \fBdns_parse_txt\fR() is used to convert raw DNS reply packet into
+struct\ \fBdns_rr_txt\fR (it is used internally and may be used directly too
+with generic query interface). Routines \fBdns_submit_txt\fR() and
+\fBdns_resolve_txt\fR() are used to perform IN MX queries in a type\-safe
+manner. The \fIname\fR parameter is the domain name in question, and
+\fIflags\fR is query flags bitmask, with one bit, DNS_NOSRCH, of practical
+interest (if the \fIname\fR is absolute, that is, it ends up with a dot,
+DNS_NOSRCH flag will be set automatically). Note that each TXT string
+as represented by \fBstruct\ dns_txt\fR, while zero\-terminated (and the
+len field of the structure does not include the terminator), may contain
+embedded null characters \-\- content of TXT records is not interpreted
+by the library in any way.
+
+.SS "DNSBL Interface"
+.PP
+A DNS\-based blocklists, or a DNSBLs, are in wide use nowadays, especially
+to protect mailservers from spammers. The library provides DNSBL interface,
+a set of routines to perform queries against DNSBLs. Routines accepts an
+IP address (IPv4 and IPv6 are both supported) and a base DNSBL zone as
+query parameters, and returns either \fBdns_rr_a4\fR or \fBdns_rr_txt\fR
+structure. Note that IPv6 interface return IPv4 RRset.
+.PP
+.nf
+struct dns_query *
+\fBdns_submit_a4dnsbl\fR(\fIctx\fR,
+ const struct in_addr *\fIaddr\fR, const char *\fIdnsbl\fR,
+ dns_query_a4_fn *\fIcbck\fR, void *\fIdata\fR, time_t \fInow\fR);
+struct dns_query *
+\fBdns_submit_a4dnsbl_txt\fR(\fIctx\fR,
+ const struct in_addr *\fIaddr\fR, const char *\fIdnsbl\fR,
+ dns_query_txt_fn *\fIcbck\fR, void *\fIdata\fR, time_t \fInow\fR);
+struct dns_query *
+\fBdns_submit_a6dnsbl\fR(\fIctx\fR,
+ const struct in6_addr *\fIaddr\fR, const char *\fIdnsbl\fR,
+ dns_query_a4_fn *\fIcbck\fR, void *\fIdata\fR, time_t \fInow\fR);
+struct dns_query *
+\fBdns_submit_a6dnsbl_txt\fR(\fIctx\fR,
+ const struct in6_addr *\fIaddr\fR, const char *\fIdnsbl\fR,
+ dns_query_txt_fn *\fIcbck\fR, void *\fIdata\fR, time_t \fInow\fR);
+struct dns_rr_a4 *\fBdns_resolve_a4dnsbl\fR(\fIctx\fR,
+ const struct in_addr *\fIaddr\fR, const char *\fIdnsbl\fR)
+struct dns_rr_txt *\fBdns_resolve_a4dnsbl_txt\fR(\fIctx\fR,
+ const struct in_addr *\fIaddr\fR, const char *\fIdnsbl\fR)
+struct dns_rr_a4 *\fBdns_resolve_a6dnsbl\fR(\fIctx\fR,
+ const struct in6_addr *\fIaddr\fR, const char *\fIdnsbl\fR)
+struct dns_rr_txt *\fBdns_resolve_a6dnsbl_txt\fR(\fIctx\fR,
+ const struct in6_addr *\fIaddr\fR, const char *\fIdnsbl\fR)
+.fi
+Perform (submit or resolve) a DNSBL query for the given \fIdnsbl\fR
+domain and an IP \fIaddr\fR in question, requesting either A or TXT
+records.
+
+.SS "RHSBL Interface"
+.PP
+RHSBL is similar to DNSBL, but instead of an IP address, the
+parameter is a domain name.
+.PP
+.nf
+struct dns_query *
+\fBdns_submit_rhsbl\fR(\fIctx\fR, const char *\fIname\fR, const char *\fIrhsbl\fR,
+ dns_query_a4_fn *\fIcbck\fR, void *\fIdata\fR, time_t \fInow\fR);
+struct dns_query *
+\fBdns_submit_rhsbl_txt\fR(\fIctx\fR, const char *\fIname\fR, const char *\fIrhsbl\fR,
+ dns_query_txt_fn *\fIcbck\fR, void *\fIdata\fR, time_t \fInow\fR);
+struct dns_rr_a4 *
+\fBdns_resolve_rhsbl\fR(\fIctx\fR, const char *\fIname\fR, const char *\fIrhsbl\fR);
+struct dns_rr_txt *
+\fBdns_resolve_rhsbl_txt\fR(\fIctx\fR, const char *\fIname\fR, const char *\fIrhsbl\fR);
+.fi
+Perform (submit or resolve) a RHSBL query for the given \fIrhsbl\fR
+domain and \fIname\fR in question, requesting either A or TXT records.
+
+
+.SH "LOW\-LEVEL INTERFACE"
+
+.SS "Domain Names (DNs)"
+
+.PP
+A DN is a series of domain name labels each starts with length byte,
+followed by empty label (label with zero length). The following
+routines to work with DNs are provided.
+
+.PP
+.nf
+unsigned \fBdns_dnlen\fR(const unsigned char *\fIdn\fR)
+.fi
+.RS
+return length of the domain name \fIdn\fR, including the terminating label.
+.RE
+
+.PP
+.nf
+unsigned \fBdns_dnlabels\fR(const unsigned char *\fIdn\fR)
+.fi
+.RS
+return number of non\-zero labels in domain name \fIdn\fR.
+.RE
+
+.PP
+.nf
+unsigned \fBdns_dnequal\fR(\fIdn1\fR, \fIdn2\fR)
+ const unsigned char *\fIdn1\fR, *\fIdn2\fR;
+.fi
+.RS
+test whenever the two domain names, \fIdn1\fR and \fIdn2\fR, are
+equal (case\-insensitive). Return domain name length if equal
+or 0 if not.
+.RE
+
+.PP
+.nf
+unsigned \fBdns_dntodn\fR(\fIsdn\fR, \fIddn\fR, \fIdnsiz\fR)
+ const unsigned char *\fIsdn\fR;
+ unsigned char *\fIddn\fR;
+ unsigned \fIdnsiz\fR;
+.fi
+.RS
+copies the source domain name \fIsdn\fR to destination buffer \fIddn\fR
+of size \fIdnsiz\fR. Return domain name length or 0 if \fIddn\fR is
+too small.
+.RE
+
+.PP
+.nf
+int \fBdns_ptodn\fR(\fIname\fR, \fInamelen\fR, \fIdn\fR, \fIdnsiz\fR, \fIisabs\fR)
+int \fBdns_sptodn\fR(\fIname\fR, \fIdn\fR, \fIdnsiz\fR)
+ const char *\fIname\fR; unsigned \fInamelen\fR;
+ unsigned char *\fIdn\fR; unsigned \fIdnsiz\fR;
+ int *\fIisabs\fR;
+.fi
+.RS
+convert asciiz name \fIname\fR of length \fInamelen\fR to DN format,
+placing result into buffer \fIdn\fR of size \fIdnsiz\fR. Return
+length of the DN if successeful, 0 if the \fIdn\fR buffer supplied is
+too small, or negative value if \fIname\fR is invalid. If \fIisabs\fR
+is non\-NULL and conversion was successeful, *\fIisabs\fR will be set to
+either 1 or 0 depending whenever \fIname\fR was absolute (i.e. ending with
+a dot) or not. Name length, \fInamelength\fR, may be zero, in which case
+strlen(\fIname\fR) will be used. Second form, \fBdns_sptodn\fR(), is a
+simplified form of \fBdns_ptodn\fR(), equivalent to
+.br
+.nf
+\fBdns_ptodn\fR(\fIname\fR, 0, \fIdn\fR, \fIdnlen\fR, 0).
+.fi
+.RE
+
+.PP
+.nf
+extern const unsigned char \fBdns_inaddr_arpa_dn\fR[]
+int \fBdns_a4todn\fR(const struct in_addr *\fIaddr\fR, const unsigned char *\fItdn\fR,
+ unsigned char *\fIdn\fR, unsigned \fIdnsiz\fR)
+int \fBdns_a4ptodn\fR(const struct in_addr *\fIaddr\fR, const char *\fItname\fR,
+ unsigned char *\fIdn\fR, unsigned \fIdnsiz\fR)
+extern const unsigned char \fBdns_ip6_arpa_dn\fR[]
+int \fBdns_a6todn\fR(const struct in6_addr *\fIaddr\fR, const unsigned char *\fItdn\fR,
+ unsigned char *\fIdn\fR, unsigned \fIdnsiz\fR)
+int \fBdns_a6ptodn\fR(const struct in6_addr *\fIaddr\fR, const char *\fItname\fR,
+ unsigned char *\fIdn\fR, unsigned \fIdnsiz\fR)
+.fi
+.RS
+several variants of routines to convert IPv4 and IPv6 address \fIaddr\fR
+into reverseDNS\-like domain name in DN format, storing result in \fIdn\fR
+of size \fIdnsiz\fR. \fItdn\fR (or \fItname\fR) is the base zone name,
+like in-addr.arpa for IPv4 or in6.arpa for IPv6. If \fItdn\fR (or \fItname\fR)
+is NULL, \fBdns_inaddr_arpa_dn\fR (or \fBdns_ip6_arpa_dn\fR) will be used.
+The routines may be used to construct a DN for a DNSBL lookup for example.
+All routines return length of the resulting DN on success, -1 if resulting
+DN is invalid, or 0 if the \fIdn\fR buffer (\fIdnsiz\fR) is too small.
+To hold standard rDNS DN, a buffer of size \fBDNS_A4RSIZE\fR (30 bytes) for
+IPv4 address, or \fBDNS_A6RSIZE\fR (74 bytes) for IPv6 address, is sufficient.
+.RE
+
+.PP
+.nf
+int \fBdns_dntop\fR(\fIdn\fR, \fIname\fR, \fInamesiz\fR)
+ const unsigned char *\fIdn\fR;
+ const char *\fIname\fR; unsigned \fInamesiz\fR;
+.fi
+.RS
+convert domain name \fIdn\fR in DN format to asciiz string, placing result
+into \fIname\fR buffer of size \fInamesiz\fR. Maximum length of asciiz
+representation of domain name is \fBDNS_MAXNAME\fR (1024) bytes. Root
+domain is represented as empty string. Return length of the resulting name
+(including terminating character, i.e. strlen(name)+1) on success, 0 if the
+\fIname\fR buffer is too small, or negative value if \fIdn\fR is invalid
+(last case should never happen since all routines in this library which
+produce domain names ensure the DNs generated are valid).
+.RE
+
+.PP
+.nf
+const char *\fBdns_dntosp\fR(const unsigned char *\fIdn\fR)
+.fi
+.RS
+convert domain name \fIdn\fR in DN format to asciiz string using static
+buffer. Return the resulting asciiz string on success or NULL on failure.
+Note since this routine uses static buffer, it is not thread\-safe.
+.RE
+
+.PP
+.nf
+unsigned \fBdns_dntop_size\fR(const unsigned char *\fIdn\fR)
+.fi
+.RS
+return the buffer size needed to convert the \fIdn\fR domain name
+in DN format to asciiz string, for \fBdns_dntop\fR(). The routine
+return either the size of buffer required, including the trailing
+zero byte, or 0 if \fIdn\fR is invalid.
+.RE
+
+.SS "Working with DNS Packets"
+
+.PP
+The following routines are provided to encode and decode DNS on\-wire
+packets. This is low\-level interface.
+
+.PP
+DNS response codes (returned by \fBdns_rcode\fR() routine) are
+defined as constants prefixed with \fBDNS_R_\fR. See dns.h
+header file for the complete list. In particular, constants
+\fBDNS_R_NOERROR\fR (0), \fBDNS_R_SERVFAIL\fR, \fBDNS_R_NXDOMAIN\fR
+may be of interest to an application.
+
+.PP
+.nf
+unsigned \fBdns_get16\fR(const unsigned char *\fIp\fR)
+unsigned \fBdns_get32\fR(const unsigned char *\fIp\fR)
+.fi
+.RS
+helper routines, convert 16\-bit or 32\-bit integer in on\-wire
+format pointed to by \fIp\fR to unsigned.
+.RE
+
+.PP
+.nf
+unsigned char *\fBdns_put16\fR(unsigned char *\fId\fR, unsigned \fIn\fR)
+unsigned char *\fBdns_put32\fR(unsigned char *\fId\fR, unsigned \fIn\fR)
+.fi
+.RS
+helper routine, convert unsigned 16\-bit or 32\-bit integer \fIn\fR to
+on\-wire format to buffer pointed to by \fId\fR, return \fId\fR+2 or
+\fId\fR+4.
+.RE
+
+.PP
+.nf
+\fBDNS_HSIZE\fR (12)
+.fi
+.RS
+defines size of DNS header. Data section
+in the DNS packet immediately follows the header. In the header,
+there are query identifier (id), various flags and codes,
+and number of resource records in various data sections.
+See dns.h header file for complete list of DNS header definitions.
+.RE
+
+.PP
+.nf
+unsigned \fBdns_qid\fB(const unsigned char *\fIpkt\fR)
+int \fBdns_rd\fB(const unsigned char *\fIpkt\fR)
+int \fBdns_tc\fB(const unsigned char *\fIpkt\fR)
+int \fBdns_aa\fB(const unsigned char *\fIpkt\fR)
+int \fBdns_qr\fB(const unsigned char *\fIpkt\fR)
+int \fBdns_ra\fB(const unsigned char *\fIpkt\fR)
+unsigned \fBdns_opcode\fB(const unsigned char *\fIpkt\fR)
+unsigned \fBdns_rcode\fB(const unsigned char *\fIpkt\fR)
+unsigned \fBdns_numqd\fB(const unsigned char *\fIpkt\fR)
+unsigned \fBdns_numan\fB(const unsigned char *\fIpkt\fR)
+unsigned \fBdns_numns\fB(const unsigned char *\fIpkt\fR)
+unsigned \fBdns_numar\fB(const unsigned char *\fIpkt\fR)
+const unsigned char *\fBdns_payload\fR(const unsigned char *\fIpkt\fR)
+.fi
+.RS
+return various parts from the DNS packet header \fIpkt\fR:
+query identifier (qid),
+recursion desired (rd) flag,
+truncation occured (tc) flag,
+authoritative answer (aa) flag,
+query response (qr) flag,
+recursion available (ra) flag,
+operation code (opcode),
+result code (rcode),
+number of entries in question section (numqd),
+number of answers (numan),
+number of authority records (numns),
+number of additional records (numar),
+and the pointer to the packet data (payload).
+.RE
+
+.PP
+.nf
+int \fBdns_getdn\fR(\fIpkt\fR, \fIcurp\fR, \fIpkte\fR, \fIdn\fR, \fIdnsiz\fR)
+const unsigned char *\fBdns_skipdn\fR(\fIcur\fR, \fIpkte\fR)
+ const unsigned char *\fIpkt\fR, *\fIpkte\fR, **\fIcurp\fR, *\fIcur\fR;
+ unsigned char *\fIdn\fR; unsigned \fIdnsiz\fR;
+.fi
+.RS
+\fBdns_getdn\fR() extract DN from DNS packet \fIpkt\fR which ends before
+\fIpkte\fR starting at position *\fIcurp\fR into buffer pointed to by
+\fIdn\fR of size \fIdnsiz\fR. Upon successeful completion, *\fIcurp\fR
+will point to the next byte in the packet after the extracted domain name.
+It return positive number (length of the DN if \fIdn\fR) upon successeful
+completion, negative value on error (when the packet contains invalid data),
+or zero if the \fIdnsiz\fR is too small (maximum length of a domain name is
+\fBDNS_MAXDN\fR). \fBdns_skipdn\fR() return pointer to the next byte in
+DNS packet which ends up before \fIpkte\fR after a domain name which starts
+at the \fIcur\fP byte, or NULL if the packet is invalid. \fBdns_skipdn\fR()
+is more or less equivalent to what \fBdns_getdn\fR() does, except it does not
+actually extract the domain name in question, and uses simpler interface.
+.RE
+
+.PP
+.nf
+struct \fBdns_rr\fR {
+ unsigned char \fBdnsrr_dn\fR[DNS_MAXDN]; /* the RR DN name */
+ enum dns_class \fBdnsrr_cls\fR; /* class of the RR */
+ enum dns_type \fBdnsrr_typ\fR; /* type of the RR */
+ unsigned \fBdnsrr_ttl\fR; /* TTL value */
+ unsigned \fBdnsrr_dsz\fR; /* size of data in bytes */
+ const unsigned char *\fBdnsrr_dptr\fR; /* pointer to the first data byte */
+ const unsigned char *\fBdnsrr_dend\fR; /* next byte after RR */
+};
+.fi
+.RS
+The \fBstruct\ dns_rr\fR structure is used to hold information about
+single DNS Resource Record (RR) in an easy to use form.
+.RE
+
+.PP
+.nf
+struct \fBdns_parse\fR {
+ const unsigned char *\fBdnsp_pkt\fR; /* pointer to the packet being parsed */
+ const unsigned char *\fBdnsp_end\fR; /* end of the packet pointer */
+ const unsigned char *\fBdnsp_cur\fR; /* current packet positionn */
+ int \fBdnsp_rrl\fR; /* number of RRs left */
+ int \fBdnsp_nrr\fR; /* number of relevant RRs seen so far */
+ unsigned \fBdnsp_ttl\fR; /* TTL value so far */
+ const unsigned char *\fBdnsp_qdn\fR; /* the domain of interest or NULL */
+ enum dns_class \fBdnsp_qcls\fR; /* class of interest or 0 for any */
+ enum dns_type \fBdnsp_qtyp\fR; /* type of interest or 0 for any */
+ unsigned char \fBdnsp_dnbuf\fR[DNS_MAXDN]; /* domain name buffer */
+};
+.fi
+.RS
+The \fBstruct dns_parse\fR structure is used to parse DNS reply packet.
+It holds information about the packet being parsed (dnsp_pkt, dnsp_end and
+dnsp_cur fields), number of RRs in the current section left to do, and
+the information about specific RR which we're looking for (dnsp_qdn,
+dnsp_qcls and dnsp_qtyp fields).
+.RE
+
+.PP
+.nf
+int \fBdns_initparse\fR(struct dns_parse *\fIp\fR,
+ enum dns_class \fIqcls\fR, enum dns_type \fIqtyp\fR,
+ const unsigned char *\fIpkt\fR, const unsigned char *\fIend\fR)
+.fi
+.RS
+initializes the RR parsing structure \fIp\fR. The \fIp\fR->\fBdnsp_qdn\fR
+field is initialized to the DN in question section, \fIp\fR->\fBdnsp_rrl\fR
+is set to number of RRs in answer section, \fIp\fR->\fBdnsp_cur\fR is
+set to point to the first RR in answer section, and \fIp\fR->\fBdnsp_ttl\fR
+will be set to max TTL value, 0xffffffff.
+.RE
+
+.PP
+.nf
+int \fBdns_nextrr\fR(struct dns_parse *\fIp\fR, struct dns_rr *\fIrr\fR);
+.fi
+.RS
+searches for next RR in the packet based on the criteria provided in
+the \fIp\fR structure, filling in the \fIrr\fR structure and
+advancing \fIp\fR->\fBdnsp_cur\fR to the next RR in the packet.
+RR selection is based on dnsp_qdn, dnsp_qcls and dnsp_qtyp fields in
+the dns_parse structure. Any (or all) of the 3 fields may be 0,
+which means any actual value from the packet is acceptable. In case
+the field isn't 0 (or NULL for dnsp_qdn), only RRs with corresponding
+characteristics are acceptable. Additionally, when dnsp_qdn is non\-NULL,
+\fBdns_nextrr\fR() performs automatic CNAME expansion.
+Routine will return positive value on success, 0 in case it reached the end
+of current section in the packet (\fIp\fR->\fBdnsp_rrl\fR is zero), or
+negative value if next RR can not be decoded (packet format is invalid).
+The routine updates \fIp\fR->\fBdnsp_qdn\fR automatically when this
+field is non\-NULL and it encounters appropriate CNAME RRs (saving CNAME
+target in \fIp\fR->\fBdnsp_dnbuf\fR), so after end of the process,
+\fIp\fR->\fBdnsp_qdn\fR will point to canonical name of the domain
+in question. The routine updates \fIp\fR->\fBdnsp_ttl\fR value to
+be the minimum TTL of all RRs found.
+.RE
+
+.PP
+.nf
+void \fBdns_rewind\fR(struct dns_parse *\fIp\fR)
+.fi
+.RS
+this routine "rewinds" the packet parse state structure to be at the
+same state as after a call to \fBdns_initparse\fR(), i.e. reposition
+the parse structure \fIp\fR to the start of answer section and
+initialize \fIp\fR->\fBdnsp_rrl\fR to the number of entries in
+answer section.
+.RE
+
+.PP
+.nf
+int \fBdns_stdrr_size\fR(const struct dns_parse *\fIp\fR);
+.fi
+.RS
+return size to hold standard RRset structure information, as shown
+in \fBstruct\ dns_rr_null\fR structure (for the query and canonical
+names). Used to calculate amount of memory to allocate for common
+part of type\-specific RR structures in parsing routines.
+.RE
+
+.PP
+.nf
+void *\fBdns_stdrr_finish\fR(struct dns_rr_null *\fIret\fR, char *\fIcp\fR,
+ const struct dns_parse *\fIp\fR);
+.fi
+.RS
+initializes standard RRset fields in \fIret\fR structure using buffer
+pointed to by \fIcp\fR, which should have at least as many bytes
+as \fBdns_stdrr_size\fR(\fIp\fR) returned. Used to finalize common
+part of type\-specific RR structures in parsing routines.
+.RE
+
+.PP
+See library source for usage examples of all the above low\-level routines,
+especially source of the parsing routines.
+
+.SH AUTHOR
+.PP
+The \fBudns\fR library has been written by Michael Tokarev, mjt at corpit.ru.
Added: branches/ppcgui/ex-libs/udns-arm/udns.h
===================================================================
--- branches/ppcgui/ex-libs/udns-arm/udns.h 2006-11-28 22:30:15 UTC (rev 2973)
+++ branches/ppcgui/ex-libs/udns-arm/udns.h 2006-11-28 23:01:41 UTC (rev 2974)
@@ -0,0 +1,689 @@
+/* $Id: udns.h,v 1.19 2004/07/09 01:18:00 mjt Exp $
+ * header file for the dns library.
+ */
+
+#ifndef UDNS_VERSION /* include guard */
+
+#define UDNS_VERSION "0.0.1"
+
+#include <assert.h>
+#ifdef WIN32
+/* NOTE: do not include 'windows.h' before 'winsock2.h'.
+ * It is included by 'winsock2.h' anyway.
+ */
+#include <winsock2.h>
+#include <ws2tcpip.h> // << Needed for 'struct in6_addr'
+#include <time.h>
+#include "win32/win32.h"
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif
+
+#ifndef AF_INET6
+struct in6_addr {
+ unsigned char s6_addr[16];
+};
+#endif
+
+/**************************************************************************/
+/**************** Common definitions **************************************/
+#ifdef WIN32
+#define DNS_INLINE __inline
+
+#if defined(DNS_DYNAMIC_LIBRARY)
+#if defined(DNS_LIBRARY_BUILD)
+// We're building the library
+#define DNS_API __declspec(dllexport)
+#define DNS_DATA_API __declspec(dllexport)
+#else // !DNS_LIBRARY_BUILD
+// User including header
+#define DNS_API __declspec(dllimport)
+#define DNS_DATA_API __declspec(dllimport)
+#endif // DNS_LIBRARY_BUILD
+#else // !DNS_DYNAMIC_LIBRARY
+/* By default, we assume that we are used as a static lib.
+ */
+#define DNS_API
+#define DNS_DATA_API extern
+#endif // DNS_DYNAMIC_LIBRARY
+
+int dns_win32_get_nameservers(struct dns_ctx *ctx);
+#define socket_close(sock) closesocket(sock)
+#define snprintf _snprintf
+typedef int socklen_t;
+
+#else // UNIX-like OSes
+
+#define DNS_INLINE inline
+#define DNS_API
+#define DNS_DATA_API extern
+#define socket_close(sock) close(sock)
+#endif
+
+extern const char *dns_version(void);
+
+struct dns_ctx;
+struct dns_query;
+
+#define DNS_MAXDN 255 /* max DN length */
+#define DNS_MAXLABEL 63 /* max DN label length */
+#define DNS_MAXNAME 1024 /* max asciiz domain name length */
+#define DNS_HSIZE 12 /* DNS packet header size */
+#define DNS_PORT 53 /* default domain port */
+#define DNS_MAXSERV 6 /* max servers to consult */
+#define DNS_MAXSRCH 5 /* max searchlist entries */
+#define DNS_MAXPACKET 512 /* max traditional-DNS UDP packet size */
+#define DNS_EDNS0PACKET 4096 /* EDNS0 packet size to use */
+
+enum dns_class { /* DNS RR Classes */
+ DNS_C_INVALID = 0, /* invalid class */
+ DNS_C_IN = 1, /* Internet */
+ DNS_C_CH = 3, /* CHAOS */
+ DNS_C_HS = 4, /* HESIOD */
+ DNS_C_ANY = 255 /* wildcard */
+};
+
+enum dns_type { /* DNS RR Types */
+ DNS_T_INVALID = 0, /* Cookie. */
+ DNS_T_A = 1, /* Host address. */
+ DNS_T_NS = 2, /* Authoritative server. */
+ DNS_T_MD = 3, /* Mail destination. */
+ DNS_T_MF = 4, /* Mail forwarder. */
+ DNS_T_CNAME = 5, /* Canonical name. */
+ DNS_T_SOA = 6, /* Start of authority zone. */
+ DNS_T_MB = 7, /* Mailbox domain name. */
+ DNS_T_MG = 8, /* Mail group member. */
+ DNS_T_MR = 9, /* Mail rename name. */
+ DNS_T_NULL = 10, /* Null resource record. */
+ DNS_T_WKS = 11, /* Well known service. */
+ DNS_T_PTR = 12, /* Domain name pointer. */
+ DNS_T_HINFO = 13, /* Host information. */
+ DNS_T_MINFO = 14, /* Mailbox information. */
+ DNS_T_MX = 15, /* Mail routing information. */
+ DNS_T_TXT = 16, /* Text strings. */
+ DNS_T_RP = 17, /* Responsible person. */
+ DNS_T_AFSDB = 18, /* AFS cell database. */
+ DNS_T_X25 = 19, /* X_25 calling address. */
+ DNS_T_ISDN = 20, /* ISDN calling address. */
+ DNS_T_RT = 21, /* Router. */
+ DNS_T_NSAP = 22, /* NSAP address. */
+ DNS_T_NSAP_PTR = 23, /* Reverse NSAP lookup (deprecated). */
+ DNS_T_SIG = 24, /* Security signature. */
+ DNS_T_KEY = 25, /* Security key. */
+ DNS_T_PX = 26, /* X.400 mail mapping. */
+ DNS_T_GPOS = 27, /* Geographical position (withdrawn). */
+ DNS_T_AAAA = 28, /* Ip6 Address. */
+ DNS_T_LOC = 29, /* Location Information. */
+ DNS_T_NXT = 30, /* Next domain (security). */
+ DNS_T_EID = 31, /* Endpoint identifier. */
+ DNS_T_NIMLOC = 32, /* Nimrod Locator. */
+ DNS_T_SRV = 33, /* Server Selection. */
+ DNS_T_ATMA = 34, /* ATM Address */
+ DNS_T_NAPTR = 35, /* Naming Authority PoinTeR */
+ DNS_T_KX = 36, /* Key Exchange */
+ DNS_T_CERT = 37, /* Certification record */
+ DNS_T_A6 = 38, /* IPv6 address (deprecates AAAA) */
+ DNS_T_DNAME = 39, /* Non-terminal DNAME (for IPv6) */
+ DNS_T_SINK = 40, /* Kitchen sink (experimentatl) */
+ DNS_T_OPT = 41, /* EDNS0 option (meta-RR) */
+ DNS_T_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 */
+DNS_API unsigned dns_dnlen(const unsigned char *dn);
+
+/* return #of labels in a DN */
+DNS_API unsigned dns_dnlabels(const unsigned char *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 */
+DNS_API unsigned dns_dnequal(const unsigned char *dn1, const unsigned char *dn2);
+
+/* copy one DN to another, size checking */
+DNS_API unsigned
+dns_dntodn(const unsigned char *sdn, unsigned char *ddn, unsigned ddnsiz);
+
+/* convert asciiz string of length namelen (0 to use strlen) to DN */
+DNS_API int
+dns_ptodn(const char *name, unsigned namelen,
+ unsigned char *dn, unsigned dnsiz,
+ int *isabs);
+
+/* simpler form of dns_ptodn() */
+#define dns_sptodn(name,dn,dnsiz) dns_ptodn((name),0,(dn),(dnsiz),0)
+
+extern const unsigned char dns_inaddr_arpa_dn[14];
+#define DNS_A4RSIZE 30
+DNS_API int dns_a4todn(const struct in_addr *addr, const unsigned char *tdn,
+ unsigned char *dn, unsigned dnsiz);
+DNS_API int dns_a4ptodn(const struct in_addr *addr, const char *tname,
+ unsigned char *dn, unsigned dnsiz);
+DNS_API unsigned char *
+dns_a4todn_(const struct in_addr *addr, unsigned char *dn, unsigned char *dne);
+
+extern const unsigned char dns_ip6_arpa_dn[10];
+#define DNS_A6RSIZE 74
+DNS_API int dns_a6todn(const struct in6_addr *addr, const unsigned char *tdn,
+ unsigned char *dn, unsigned dnsiz);
+DNS_API int dns_a6ptodn(const struct in6_addr *addr, const char *tname,
+ unsigned char *dn, unsigned dnsiz);
+DNS_API unsigned char *
+dns_a6todn_(const struct in6_addr *addr, unsigned char *dn, unsigned char *dne);
+
+/* convert DN into asciiz string */
+DNS_API int dns_dntop(const unsigned char *dn, char *name, unsigned namesiz);
+
+/* convert DN into asciiz string, using static buffer (NOT thread-safe!) */
+DNS_API const char *dns_dntosp(const unsigned char *dn);
+
+/* return buffer size (incl. null byte) required for asciiz form of a DN */
+DNS_API unsigned dns_dntop_size(const unsigned char *dn);
+
+/**************************************************************************/
+/**************** DNS raw packet layout ***********************************/
+
+enum dns_rcode { /* reply codes */
+ DNS_R_NOERROR = 0, /* ok, no error */
+ DNS_R_FORMERR = 1, /* format error */
+ DNS_R_SERVFAIL = 2, /* server failed */
+ DNS_R_NXDOMAIN = 3, /* domain does not exists */
+ DNS_R_NOTIMPL = 4, /* not implemented */
+ DNS_R_REFUSED = 5, /* query refused */
+ /* these are for BIND_UPDATE */
+ DNS_R_YXDOMAIN = 6, /* Name exists */
+ DNS_R_YXRRSET = 7, /* RRset exists */
+ DNS_R_NXRRSET = 8, /* RRset does not exist */
+ DNS_R_NOTAUTH = 9, /* Not authoritative for zone */
+ DNS_R_NOTZONE = 10, /* Zone of record different from zone section */
+ /*ns_r_max = 11,*/
+ /* The following are TSIG extended errors */
+ DNS_R_BADSIG = 16,
+ DNS_R_BADKEY = 17,
+ DNS_R_BADTIME = 18
+};
+
+static DNS_INLINE unsigned dns_get16(const unsigned char *s) {
+ return ((unsigned)s[0]<<8) | s[1];
+}
+static DNS_INLINE unsigned dns_get32(const unsigned char *s) {
+ return ((unsigned)s[0]<<24) | ((unsigned)s[1]<<16)
+ | ((unsigned)s[2]<<8) | s[3];
+}
+static DNS_INLINE unsigned char *dns_put16(unsigned char *d, unsigned n) {
+ *d++ = (n >> 8) & 255; *d++ = n & 255; return d;
+}
+static DNS_INLINE unsigned char *dns_put32(unsigned char *d, unsigned n) {
+ *d++ = (n >> 24) & 255; *d++ = (n >> 16) & 255;
+ *d++ = (n >> 8) & 255; *d++ = n & 255;
+ return d;
+}
+
+/* DNS Header layout */
+enum {
+ /* bytes 0:1 - query ID */
+ DNS_H_QID1 = 0,
+ DNS_H_QID2 = 1,
+ DNS_H_QID = DNS_H_QID1,
+#define dns_qid(pkt) dns_get16((pkt)+DNS_H_QID)
+ /* byte 2: flags1 */
+ DNS_H_F1 = 2,
+ DNS_HF1_QR = 0x80, /* query response flag */
+#define dns_qr(pkt) ((pkt)[DNS_H_F1]&DNS_HF1_QR)
+ DNS_HF1_OPCODE = 0x78, /* opcode, 0 = query */
+#define dns_opcode(pkt) (((pkt)[DNS_H_F1]&DNS_HF1_OPCODE)>>3)
+ DNS_HF1_AA = 0x04, /* auth answer */
+#define dns_aa(pkt) ((pkt)[DNS_H_F1]&DNS_HF1_AA)
+ DNS_HF1_TC = 0x02, /* truncation flag */
+#define dns_tc(pkt) ((pkt)[DNS_H_F1]&DNS_HF1_TC)
+ DNS_HF1_RD = 0x01, /* recursion desired (may be set in query) */
+#define dns_rd(pkt) ((pkt)[DNS_H_F1]&DNS_HF1_RD)
+ /* byte 3: flags2 */
+ DNS_H_F2 = 3,
+ DNS_HF2_RA = 0x80, /* recursion available */
+#define dns_ra(pkt) ((pkt)[DNS_H_F2]&DNS_HF2_RA)
+ DNS_HF2_Z = 0x70, /* reserved */
+ DNS_HF2_RCODE = 0x0f, /* response code, DNS_R_XXX above */
+#define dns_rcode(pkt) ((pkt)[DNS_H_F2]&DNS_HF2_RCODE)
+ /* bytes 4:5: qdcount, numqueries */
+ DNS_H_QDCNT1 = 4,
+ DNS_H_QDCNT2 = 5,
+ DNS_H_QDCNT = DNS_H_QDCNT1,
+#define dns_numqd(pkt) dns_get16((pkt)+4)
+ /* bytes 6:7: ancount, numanswers */
+ DNS_H_ANCNT1 = 6,
+ DNS_H_ANCNT2 = 7,
+ DNS_H_ANCNT = DNS_H_ANCNT1,
+#define dns_numan(pkt) dns_get16((pkt)+6)
+ /* bytes 8:9: nscount, numauthority */
+ DNS_H_NSCNT1 = 8,
+ DNS_H_NSCNT2 = 9,
+ DNS_H_NSCNT = DNS_H_NSCNT1,
+#define dns_numns(pkt) dns_get16((pkt)+8)
+ /* bytes 10:11: arcount, numadditional */
+ DNS_H_ARCNT1 = 10,
+ DNS_H_ARCNT2 = 11,
+ DNS_H_ARCNT = DNS_H_ARCNT1,
+#define dns_numar(pkt) dns_get16((pkt)+10)
+#define dns_payload(pkt) ((pkt)+DNS_HSIZE)
+};
+
+/* packet buffer: start at pkt, end before pkte, current pos *curp.
+ * extract a DN and set *curp to the next byte after DN in packet.
+ * return -1 on error, 0 if dnsiz is too small, or dnlen on ok.
+ */
+DNS_API int
+dns_getdn(const unsigned char *pkt,
+ const unsigned char **curp,
+ const unsigned char *pkte,
+ unsigned char *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 */
+DNS_API const unsigned char *
+dns_skipdn(const unsigned char *pkte, const unsigned char *cur);
+
+struct dns_rr { /* DNS Resource Record */
+ unsigned char 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 */
+ const unsigned char *dnsrr_dptr; /* pointer to start of data */
+ const unsigned char *dnsrr_dend; /* past end of data */
+};
+
+struct dns_parse { /* RR/packet parsing state */
+ const unsigned char *dnsp_pkt; /* start of the packet */
+ const unsigned char *dnsp_end; /* end of the packet */
+ const unsigned char *dnsp_cur; /* current packet position */
+ int dnsp_rrl; /* number of RRs left to go */
+ int dnsp_nrr; /* RR count so far */
+ unsigned dnsp_ttl; /* TTL value so far */
+ const unsigned char *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 */
+ unsigned char dnsp_dnbuf[DNS_MAXDN];
+};
+
+/* initialize the parse structure */
+int dns_initparse(struct dns_parse *p, int qcls, int qtyp,
+ const unsigned char *pkt, const unsigned char *pkte);
+
+/* search next RR, <0=error, 0=no more RRs, >0 = found. */
+int dns_nextrr(struct dns_parse *p, struct dns_rr *rr);
+
+/* equivalent to dns_initparse() followed by dns_nextrr() */
+int dns_firstrr(struct dns_parse *p, struct dns_rr *rr, int qcls, int qtyp,
+ const unsigned char *pkt, const unsigned char *pkte);
+void dns_rewind(struct dns_parse *p);
+
+
+/**************************************************************************/
+/**************** Resolver Context ****************************************/
+
+/* default resolver context */
+extern struct dns_ctx dns_defctx;
+
+/* initialize default resolver context and open it if do_open is true.
+ * <0 on failure. */
+DNS_API int dns_init(int do_open);
+
+/* return new resolver context with the same settings as copy */
+DNS_API struct dns_ctx *dns_new(const struct dns_ctx *copy);
+
+/* free resolver context; all queries are dropped */
+DNS_API void dns_free(struct dns_ctx *ctx);
+
+DNS_API int dns_add_serv(struct dns_ctx *ctx, const char *ns);
+
+/* set nameserver list for a resolver context */
+DNS_API int dns_set_serv(struct dns_ctx *ctx, const char *serv[]);
+
+/* set search list for a resolver context */
+DNS_API int dns_set_srch(struct dns_ctx *ctx, const char *srch[]);
+
+/* set options for a resolver context */
+DNS_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 */
+DNS_API int dns_set_opt(struct dns_ctx *ctx, enum dns_opt opt, int val);
+
+enum dns_flags {
+ DNS_NOSRCH = 0x00010000, /* do not perform search */
+ DNS_NORD = 0x00020000, /* request no recursion */
+ DNS_AAONLY = 0x00040000, /* set AA flag in queries */
+ DNS_PASSALL = 0x00080000, /* pass all replies to application */
+};
+
+/* set the debug function pointer */
+DNS_API void dns_set_dbgfn(struct dns_ctx *ctx, void (*fn)(const unsigned char*,int));
+
+/* open and return UDP socket */
+DNS_API int dns_open(struct dns_ctx *ctx);
+
+/* return UDP socket or -1 if not open */
+DNS_API int dns_sock(const struct dns_ctx *ctx);
+
+/* close the UDP socket */
+DNS_API void dns_close(struct dns_ctx *ctx);
+
+/* return true if any request queued */
+DNS_API int dns_active(const struct dns_ctx *ctx);
+
+/* return status of the last operation */
+DNS_API int dns_status(const struct dns_ctx *ctx);
+void dns_setstatus(struct dns_ctx *ctx, int status);
+
+/* handle I/O event on UDP socket */
+DNS_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 */
+DNS_API int dns_timeouts(struct dns_ctx *ctx, int maxwait, time_t now);
+
+/* define timer requesting routine to use */
+typedef int dns_utm_fn(void *arg, struct dns_query *q, int timeout);
+void dns_set_tmcbck(struct dns_ctx *ctx, dns_utm_fn *utmfn, void *arg);
+/* routine to call as timer callback */
+void dns_tmevent(struct dns_query *q, time_t now);
+
+/**************************************************************************/
+/**************** 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(const unsigned char *pkt, const unsigned char *pkte, 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 */
+DNS_API struct dns_query *
+dns_submit_dn(struct dns_ctx *ctx,
+ const unsigned char *dn, int qcls, int qtyp, int flags,
+ dns_parse_fn *parse, dns_query_fn *cbck, void *data, time_t now);
+/* submit generic name query */
+DNS_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, time_t now);
+
+/* cancel the given async query in progress */
+DNS_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 */
+DNS_API void *
+dns_resolve_dn(struct dns_ctx *ctx,
+ const unsigned char *qdn, int qcls, int qtyp, int flags,
+ dns_parse_fn *parse);
+DNS_API void *
+dns_resolve_p(struct dns_ctx *ctx,
+ const char *qname, int qcls, int qtyp, int flags,
+ dns_parse_fn *parse);
+DNS_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);
+};
+
+int dns_stdrr_size(const struct dns_parse *p);
+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 */
+};
+
+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 */
+DNS_API struct dns_query *
+dns_submit_a4(struct dns_ctx *ctx, const char *name, int flags,
+ dns_query_a4_fn *cbck, void *data, time_t now);
+
+/* resolve A IN query */
+DNS_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 */
+};
+
+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 */
+DNS_API struct dns_query *
+dns_submit_a6(struct dns_ctx *ctx, const char *name, int flags,
+ dns_query_a6_fn *cbck, void *data, time_t now);
+
+/* resolve AAAA IN query */
+DNS_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 */
+};
+
+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 */
+DNS_API struct dns_query *
+dns_submit_a4ptr(struct dns_ctx *ctx, const struct in_addr *addr,
+ dns_query_ptr_fn *cbck, void *data, time_t now);
+/* resolve PTR IN in-addr.arpa query */
+DNS_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 */
+DNS_API struct dns_query *
+dns_submit_a6ptr(struct dns_ctx *ctx, const struct in6_addr *addr,
+ dns_query_ptr_fn *cbck, void *data, time_t now);
+DNS_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 */
+};
+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 */
+DNS_API struct dns_query *
+dns_submit_mx(struct dns_ctx *ctx, const char *name, int flags,
+ dns_query_mx_fn *cbck, void *data, time_t now);
+/* resolve MX IN query */
+DNS_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 */
+ unsigned char *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 */
+};
+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 */
+DNS_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, time_t now);
+/* resolve TXT query */
+DNS_API struct dns_rr_txt *
+dns_resolve_txt(struct dns_ctx *ctx, const char *name, int qcls, int flags);
+
+DNS_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, time_t now);
+DNS_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, time_t now);
+DNS_API struct dns_rr_a4 *
+dns_resolve_a4dnsbl(struct dns_ctx *ctx,
+ const struct in_addr *addr, const char *dnsbl);
+DNS_API struct dns_rr_txt *
+dns_resolve_a4dnsbl_txt(struct dns_ctx *ctx,
+ const struct in_addr *addr, const char *dnsbl);
+
+DNS_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, time_t now);
+DNS_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, time_t now);
+DNS_API struct dns_rr_a4 *
+dns_resolve_a6dnsbl(struct dns_ctx *ctx,
+ const struct in6_addr *addr, const char *dnsbl);
+DNS_API struct dns_rr_txt *
+dns_resolve_a6dnsbl_txt(struct dns_ctx *ctx,
+ const struct in6_addr *addr, const char *dnsbl);
+
+DNS_API struct dns_query *
+dns_submit_rhsbl(struct dns_ctx *ctx,
+ const char *name, const char *rhsbl,
+ dns_query_a4_fn *cbck, void *data, time_t now);
+DNS_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, time_t now);
+DNS_API struct dns_rr_a4 *
+dns_resolve_rhsbl(struct dns_ctx *ctx, const char *name, const char *rhsbl);
+DNS_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;
+};
+
+DNS_DATA_API const struct dns_nameval dns_classtab[];
+DNS_DATA_API const struct dns_nameval dns_typetab[];
+DNS_DATA_API const struct dns_nameval dns_rcodetab[];
+
+DNS_API int dns_findname(const struct dns_nameval *nv, const char *name);
+#define dns_findclassname(class) dns_findname(dns_classtab, (class))
+#define dns_findtypename(type) dns_findname(dns_typetab, (type))
+#define dns_findrcodename(rcode) dns_findname(dns_rcodetab, (rcode))
+
+DNS_API const char *dns_classname(enum dns_class class);
+DNS_API const char *dns_typename(enum dns_type type);
+DNS_API const char *dns_rcodename(enum dns_rcode rcode);
+
+DNS_API const char *dns_strerror(int errnum);
+/**
+ * Log level for UDNS log messages.
+ */
+enum dns_log_level
+{
+ DNS_LOG_DEBUG = 0,
+ DNS_LOG_INFO = 2,
+ DNS_LOG_WARN = 4,
+ DNS_LOG_ERROR = 8
+};
+#define UDNS_LOG_LEVEL_MIN DNS_LOG_WARN
+/**
+ * Function for logging messages.
+ */
+void dns_log(struct dns_ctx *ctx, enum dns_log_level level, const char *msg, ...);
+/**
+ * Converts a string representing a address into the corresponding network address structure.
+ * @addrstr The string to convert
+ * @sa Pointer to struct sockaddr_storage to which the resulting network address will be written.
+ * @return 0 on success
+ * @note Works for IPv4 and IPv6
+ */
+int dns_str2addr(const char *addrstr, struct sockaddr_storage *sa);
+/**
+ * Converts a string representing a address into the corresponding network address structure.
+ * @addrstr The string to convert
+ * @sa Pointer to struct sockaddr_storage to which the resulting network address will be written.
+ * @return 0 on success
+ * @note Works for IPv4 and IPv6
+ */
+int dns_addr2str(struct sockaddr *addr, char *buf, int len);
+/**
+ * Returns actual the length of the supplied sockaddr structure.
+ * @param sa Pointer to sockaddr structure
+ * @return length of supplied sockaddr structure in bytes.
+ * @note Works for IPv4 and IPv6
+ */
+socklen_t dns_sockaddr_get_len(struct sockaddr *sa);
+/**
+ * Sets the port member of a sockaddr structure.
+ * @param sa Pointer to sockaddr structure
+ * @param port The port number
+ * @return length of supplied sockaddr structure in bytes.
+ * @note Works for IPv4 and IPv6
+ */
+int dns_sockaddr_set_port(struct sockaddr *sa, int port);
+#endif /* include guard */
Added: branches/ppcgui/ex-libs/udns-arm/udns_bl.c
===================================================================
--- branches/ppcgui/ex-libs/udns-arm/udns_bl.c 2006-11-28 22:30:15 UTC (rev 2973)
+++ branches/ppcgui/ex-libs/udns-arm/udns_bl.c 2006-11-28 23:01:41 UTC (rev 2974)
@@ -0,0 +1,138 @@
+/* $Id: udns_bl.c,v 1.6 2004/06/30 10:43:36 mjt Exp $
+ * DNSBL stuff
+ */
+
+#include "udns.h"
+
+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, time_t now) {
+ unsigned char 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, now);
+}
+
+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, time_t now) {
+ unsigned char 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, now);
+}
+
+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, 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, 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, time_t now) {
+ unsigned char 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, now);
+}
+
+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, time_t now) {
+ unsigned char 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, now);
+}
+
+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, 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, 0));
+}
+
+static int
+dns_rhsbltodn(const char *name, const char *rhsbl, unsigned char 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, time_t now) {
+ unsigned char 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, now);
+}
+struct dns_query *
+dns_submit_rhsbl_txt(struct dns_ctx *ctx, const char *name, const char *rhsbl,
+ dns_query_txt_fn *cbck, void *data, time_t now) {
+ unsigned char 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, now);
+}
+
+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, 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, 0));
+}
Added: branches/ppcgui/ex-libs/udns-arm/udns_dn.c
===================================================================
--- branches/ppcgui/ex-libs/udns-arm/udns_dn.c 2006-11-28 22:30:15 UTC (rev 2973)
+++ branches/ppcgui/ex-libs/udns-arm/udns_dn.c 2006-11-28 23:01:41 UTC (rev 2974)
@@ -0,0 +1,366 @@
+/* $Id: udns_dn.c,v 1.3 2004/06/29 07:46:39 mjt Exp $
+ * domain names manipulation routines
+ */
+
+#include <string.h>
+#include "udns.h"
+
+unsigned dns_dnlen(const unsigned char *dn) {
+ register const unsigned char *d = dn;
+ while(*d)
+ d += 1 + *d;
+ return (unsigned)(d - dn) + 1;
+}
+
+unsigned dns_dnlabels(register const unsigned char *dn) {
+ register unsigned l = 0;
+ while(*dn)
+ ++l, dn += 1 + *dn;
+ return l;
+}
+
+unsigned dns_dnequal(register const unsigned char *dn1,
+ register const unsigned char *dn2) {
+ register unsigned c;
+ const unsigned char *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(const unsigned char *sdn, unsigned char *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,
+ unsigned char *dn, unsigned dnsiz,
+ int *isabs)
+{
+ unsigned char *dp; /* current position in dn (len byte first) */
+ unsigned char *const de /* end of dn: last byte that can be filled up */
+ = dn + (dnsiz >= DNS_MAXDN ? DNS_MAXDN : dnsiz) - 1;
+ const unsigned char *np = (const unsigned char *)name;
+ const unsigned char *ne = np + (namelen ? namelen : strlen(np));
+ unsigned char *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 == (const unsigned char *)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] = (unsigned char)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++ = (unsigned char)c; /* place next out byte */
+ }
+
+ if ((c = dp - llab) > DNS_MAXLABEL)
+ return -1; /* label too long */
+ if ((llab[-1] = (unsigned char)c) != 0) {
+ *dp++ = 0;
+ if (isabs)
+ *isabs = 0;
+ }
+ else if (isabs)
+ *isabs = 1;
+
+ return dp - dn;
+}
+
+const unsigned char dns_inaddr_arpa_dn[14] = "\07in-addr\04arpa";
+
+unsigned char *
+dns_a4todn_(const struct in_addr *addr, unsigned char *dn, unsigned char *dne) {
+ unsigned char *p;
+ unsigned n;
+ const unsigned char *s = ((const unsigned char *)addr) + 4;
+ while(--s >= (const unsigned char *)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, const unsigned char *tdn,
+ unsigned char *dn, unsigned dnsiz) {
+ unsigned char *dne = dn + (dnsiz > DNS_MAXDN ? DNS_MAXDN : dnsiz);
+ unsigned char *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,
+ unsigned char *dn, unsigned dnsiz) {
+ unsigned char *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;
+}
+
+const unsigned char dns_ip6_arpa_dn[10] = "\03ip6\04arpa";
+
+unsigned char *
+dns_a6todn_(const struct in6_addr *addr,
+ unsigned char *dn, unsigned char *dne) {
+ unsigned n;
+ const unsigned char *s = ((const unsigned char *)addr) + 16;
+ if (dn + 64 > dne) return 0;
+ while(--s >= (const unsigned char *)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, const unsigned char *tdn,
+ unsigned char *dn, unsigned dnsiz) {
+ unsigned char *dne = dn + (dnsiz > DNS_MAXDN ? DNS_MAXDN : dnsiz);
+ unsigned char *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,
+ unsigned char *dn, unsigned dnsiz) {
+ unsigned char *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(const unsigned char *dn) {
+ unsigned size = 0; /* the size reqd */
+ const unsigned char *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(const unsigned char *dn, char *name, unsigned namesiz) {
+ char *np = name; /* current name ptr */
+ char *const ne = name + namesiz; /* end of name */
+ const unsigned char *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;
+ unsigned char dn[DNS_MAXDN+10];
+ unsigned char *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 */
Added: branches/ppcgui/ex-libs/udns-arm/udns_dntosp.c
===================================================================
--- branches/ppcgui/ex-libs/udns-arm/udns_dntosp.c 2006-11-28 22:30:15 UTC (rev 2973)
+++ branches/ppcgui/ex-libs/udns-arm/udns_dntosp.c 2006-11-28 23:01:41 UTC (rev 2974)
@@ -0,0 +1,11 @@
+/* $Id: udns_dntosp.c,v 1.3 2004/06/29 07:46:39 mjt Exp $
+ * dns_dntosp() = convert DN to asciiz string using static buffer
+ */
+
+#include "udns.h"
+
+static char name[DNS_MAXNAME];
+
+const char *dns_dntosp(const unsigned char *dn) {
+ return dns_dntop(dn, name, sizeof(name)) > 0 ? name : 0;
+}
Added: branches/ppcgui/ex-libs/udns-arm/udns_misc.c
===================================================================
--- branches/ppcgui/ex-libs/udns-arm/udns_misc.c 2006-11-28 22:30:15 UTC (rev 2973)
+++ branches/ppcgui/ex-libs/udns-arm/udns_misc.c 2006-11-28 23:01:41 UTC (rev 2974)
@@ -0,0 +1,231 @@
+/* $Id: udns_misc.c,v 1.5 2004/07/02 00:14:48 mjt Exp $
+ */
+
+#include "udns.h"
+#include <stdio.h>
+#include <string.h>
+#ifndef WIN32
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#endif
+
+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_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";
+ }
+}
+
+/**
+ * @todo use dns_ctx debug function if availible, otherwise suppress output.
+ */
+void dns_log(struct dns_ctx *ctx, enum dns_log_level level, const char *msg, ...)
+{
+ va_list va;
+ const char *level_str;
+#define DNS_LOG_PREFIX_LEN 1024
+ char prefix[DNS_LOG_PREFIX_LEN];
+
+ if(level < UDNS_LOG_LEVEL_MIN)
+ return;
+
+ switch(level)
+ {
+ case DNS_LOG_DEBUG: level_str = "DEBUG"; break;
+ case DNS_LOG_INFO: level_str = "INFO"; break;
+ case DNS_LOG_WARN: level_str = "WARN"; break;
+ case DNS_LOG_ERROR: level_str = "ERROR"; break;
+ default: level_str = "DEBUG"; break;
+ }
+ snprintf(prefix, DNS_LOG_PREFIX_LEN, "UDNS-%s: ", level_str);
+ fprintf(stdout, prefix);
+ va_start(va, msg);
+ vfprintf(stdout, msg, va);
+ va_end(va);
+#undef DNS_LOG_PREFIX_LEN
+}
+
+int dns_str2addr(const char *addrstr, struct sockaddr_storage *sa)
+{
+ int af = 0;
+ #ifdef WIN32
+ int len = sizeof(struct sockaddr_storage);
+ #else
+ void *addrptr = NULL;
+ #endif
+
+ if(!addrstr)
+ return -1;
+
+ if(strchr(addrstr, ':'))
+ af = AF_INET6;
+ else if(strchr(addrstr, '.'))
+ af = AF_INET;
+ else
+ return -1;
+
+#ifdef WIN32
+ if(WSAStringToAddress(addrstr, af, NULL, sa, &len))
+ return -1;
+#else
+ memset(sa, 0x0, sizeof(struct sockaddr_storage));
+ switch(af)
+ {
+ case AF_INET:
+ addrptr = &(((struct sockaddr_in*) sa)->sin_addr);
+ ((struct sockaddr_in*) sa)->sin_family = AF_INET;
+ break;
+ case AF_INET6:
+ addrptr = &(((struct sockaddr_in6*) sa)->sin6_addr);
+ ((struct sockaddr_in6*) sa)->sin6_family = AF_INET6;
+ break;
+ default:
+ // !! Protocol family not supported !
+ return -2;
+ }
+ assert(addrptr != NULL);
+ if(inet_pton(af, addrstr, addrptr) <= 0)
+ return -1;
+#endif
+ return 0;
+}
+
+int dns_addr2str(struct sockaddr *addr, char *buf, int len)
+{
+ int err;
+ #ifdef WIN32
+ int chars_written;
+ int addrlen = dns_sockaddr_get_len(addr);
+ char *temp;
+ #else
+ char *result;
+ void *addrptr;
+ #endif
+
+ assert(addr != NULL);
+ assert(buf != NULL);
+ assert(len > 0);
+
+ *buf = '\0';
+
+ #ifdef WIN32
+ chars_written = len;
+ if(WSAAddressToString(addr, addrlen, NULL, buf, &chars_written) == SOCKET_ERROR)
+ {
+ // !! Error !
+ err = WSAGetLastError();
+ /* NOTE: if the buffer was to small, WSAAddressToString() fails with
+ * WSAEFAULT and writes the number of bytes actually needed to complete
+ * the operation in chars_written.
+ */
+ if(err == WSAEFAULT && chars_written > len)
+ {
+ // !! Not enough space in user buffer !
+ err = -3;
+ }
+ else if(err == WSAEINVAL)
+ {
+ // !! Protocol family not supported !
+ err = -2;
+ }
+ else
+ {
+ // !! Generic error !
+ err = -1;
+ }
+ return err;
+ }
+ temp = strchr(buf,':');
+ if(temp)
+ *temp='\0';
+ #else
+ switch(addr->sa_family)
+ {
+ case PF_INET:
+ addrptr = &(((struct sockaddr_in*) addr)->sin_addr);
+ break;
+ case PF_INET6:
+ addrptr = &(((struct sockaddr_in6*) addr)->sin6_addr);
+ break;
+ default:
+ // !! Protocol family not supported !
+ return -2;
+ }
+
+ result = (char*) inet_ntop(addr->sa_family, addrptr, buf, len);
+ if(result == NULL)
+ {
+ // !! Error !
+
+ if(errno == EAFNOSUPPORT)
+ {
+ // !! Protocol family not supported !
+ err = -2;
+ }
+ else if(errno == ENOSPC)
+ {
+ // !! Not enough space in user buffer !
+ err = -3;
+ }
+ else
+ {
+ // !! Generic error !
+ err = -1;
+ }
+ return err;
+ }
+
+ #endif
+
+ // No error
+ return 0;
+}
+
+socklen_t dns_sockaddr_get_len(struct sockaddr *sa)
+{
+ switch(sa->sa_family)
+ {
+ case AF_INET:
+ return sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ return sizeof(struct sockaddr_in6);
+ break;
+ default:
+ return 0; // don't return -1, this would be very dangerous
+ }
+}
+
+int dns_sockaddr_set_port(struct sockaddr *sa, int port)
+{
+ switch(sa->sa_family)
+ {
+ case AF_INET:
+ ((struct sockaddr_in*) sa)->sin_port = htons(port);
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6*) sa)->sin6_port = htons(port);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
Added: branches/ppcgui/ex-libs/udns-arm/udns_parse.c
===================================================================
--- branches/ppcgui/ex-libs/udns-arm/udns_parse.c 2006-11-28 22:30:15 UTC (rev 2973)
+++ branches/ppcgui/ex-libs/udns-arm/udns_parse.c 2006-11-28 23:01:41 UTC (rev 2974)
@@ -0,0 +1,163 @@
+/* $Id: udns_parse.c,v 1.10 2004/07/02 21:52:04 mjt Exp $
+ * raw DNS packet parsing routines
+ */
+
+#include <string.h>
+#include <assert.h>
+#include "udns.h"
+
+const unsigned char *
+dns_skipdn(const unsigned char *cur, const unsigned char *pkte) {
+ unsigned c;
+ for(;;) {
+ if (cur >= pkte)
+ return NULL;
+ c = *cur++;
+ if (!c)
+ return cur;
+ if (c & 192) { /* jump */
+ return cur + 1 >= pkte ? NULL : cur + 1;
+ }
+ cur += c;
+ }
+}
+
+int
+dns_getdn(const unsigned char *pkt,
+ const unsigned char **curp,
+ const unsigned char *pkte,
+ register unsigned char *dn, unsigned dnsiz) {
+ unsigned c;
+ const unsigned char *cp = *curp; /* max jump position (jump only back) */
+ const un