summaryrefslogtreecommitdiffhomepage
path: root/adns-0.6/src
diff options
context:
space:
mode:
Diffstat (limited to 'adns-0.6/src')
-rw-r--r--adns-0.6/src/.cvsignore2
-rw-r--r--adns-0.6/src/Makefile.in48
-rw-r--r--adns-0.6/src/adns.h818
-rw-r--r--adns-0.6/src/adns.make25
-rw-r--r--adns-0.6/src/check.c199
-rw-r--r--adns-0.6/src/config.h.in91
-rw-r--r--adns-0.6/src/dlist.h53
-rw-r--r--adns-0.6/src/event.c699
-rw-r--r--adns-0.6/src/general.c360
-rw-r--r--adns-0.6/src/internal.h705
-rw-r--r--adns-0.6/src/parse.c253
-rw-r--r--adns-0.6/src/poll.c131
-rw-r--r--adns-0.6/src/query.c540
-rw-r--r--adns-0.6/src/reply.c357
-rw-r--r--adns-0.6/src/setup.c643
-rw-r--r--adns-0.6/src/transmit.c257
-rw-r--r--adns-0.6/src/tvarith.h41
-rw-r--r--adns-0.6/src/types.c1034
18 files changed, 0 insertions, 6256 deletions
diff --git a/adns-0.6/src/.cvsignore b/adns-0.6/src/.cvsignore
deleted file mode 100644
index 547646a..0000000
--- a/adns-0.6/src/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-config.h
diff --git a/adns-0.6/src/Makefile.in b/adns-0.6/src/Makefile.in
deleted file mode 100644
index 7afca95..0000000
--- a/adns-0.6/src/Makefile.in
+++ /dev/null
@@ -1,48 +0,0 @@
-# src/Makefile - library main Makefile
-#
-# This file is
-# Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
-#
-# It is part of adns, which is
-# Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
-# Copyright (C) 1999 Tony Finch <dot@dotat.at>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-srcdir= @srcdir@
-VPATH= @srcdir@
-
-TARGETS= libadns.a
-include $(srcdir)/../settings.make
-include adns.make
-
-install: libadns.a
- set -xe; for f in $(TARGETS); \
- do $(INSTALL_DATA) $$f $(lib_dir)/$$f; done
- $(INSTALL_DATA) $(srcdir)/../src/adns.h $(include_dir)/adns.h
-
-uninstall:
- for f in $(TARGETS); do rm -f $(lib_dir)/$$f; done
- rm -f $(include_dir)/adns.h
-
-ALLOBJS= $(LIBOBJS)
-
-libadns.a: $(LIBOBJS)
- rm -f $@
- $(AR) cqv $@.new $(LIBOBJS)
- $(RANLIB) $@.new
- mv -f $@.new $@
-
-$(LIBOBJS): adns.h internal.h config.h
diff --git a/adns-0.6/src/adns.h b/adns-0.6/src/adns.h
deleted file mode 100644
index 588acba..0000000
--- a/adns-0.6/src/adns.h
+++ /dev/null
@@ -1,818 +0,0 @@
-/*
- * adns.h
- * - adns user-visible API (single-threaded, without any locking)
- */
-/*
- *
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- *
- * For the benefit of certain LGPL'd `omnibus' software which provides
- * a uniform interface to various things including adns, I make the
- * following additional licence. I do this because the GPL would
- * otherwise force either the omnibus software to be GPL'd or for the
- * adns-using part to be distributed separately.
- *
- * So, you may also redistribute and/or modify adns.h (but only the
- * public header file adns.h and not any other part of adns) under the
- * terms of the GNU Library General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * Note that adns itself is GPL'd. Authors of adns-using applications
- * with GPL-incompatible licences, and people who distribute adns with
- * applications where the whole distribution is not GPL'd, are still
- * likely to be in violation of the GPL. Anyone who wants to do this
- * should contact Ian Jackson. Please note that to avoid encouraging
- * people to infringe the GPL as it applies the body of adns, I think
- * that if you take advantage of the special exception to redistribute
- * just adns.h under the LGPL, you should retain this paragraph in its
- * place in the appropriate copyright statements.
- *
- *
- * You should have received a copy of the GNU General Public License,
- * or the GNU Library General Public License, as appropriate, along
- * with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *
- * $Id: adns.h,v 1.1.1.1 2000-02-16 17:32:46 sdyoung Exp $
- */
-
-#ifndef ADNS_H_INCLUDED
-#define ADNS_H_INCLUDED
-#ifdef __cplusplus
-extern "C" { /* I really dislike this - iwj. */
-#endif
-
-#include <stdio.h>
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <unistd.h>
-
-/* All struct in_addr anywhere in adns are in NETWORK byte order. */
-
-typedef struct adns__state *adns_state;
-typedef struct adns__query *adns_query;
-
-typedef enum {
- adns_if_noenv= 0x0001, /* do not look at environment */
- adns_if_noerrprint= 0x0002, /* never print output to stderr (_debug overrides) */
- adns_if_noserverwarn= 0x0004, /* do not warn to stderr about duff nameservers etc */
- adns_if_debug= 0x0008, /* enable all output to stderr plus debug msgs */
- adns_if_logpid= 0x0080, /* include pid in diagnostic output */
- adns_if_noautosys= 0x0010, /* do not make syscalls at every opportunity */
- adns_if_eintr= 0x0020, /* allow _wait and _synchronous to return EINTR */
- adns_if_nosigpipe= 0x0040, /* applic has SIGPIPE set to SIG_IGN, do not protect */
- adns_if_checkc_entex= 0x0100, /* do consistency checks on entry/exit to adns funcs */
- adns_if_checkc_freq= 0x0300 /* do consistency checks very frequently (slow!) */
-} adns_initflags;
-
-typedef enum {
- adns_qf_search= 0x00000001, /* use the searchlist */
- adns_qf_usevc= 0x00000002, /* use a virtual circuit (TCP connection) */
- adns_qf_owner= 0x00000004, /* fill in the owner field in the answer */
- adns_qf_quoteok_query= 0x00000010, /* allow quote-requiring chars in query domain */
- adns_qf_quoteok_cname= 0x00000000, /* allow ... in CNAME we go via - now default */
- adns_qf_quoteok_anshost= 0x00000040, /* allow ... in things supposed to be hostnames */
- adns_qf_quotefail_cname= 0x00000080, /* refuse if quote-req chars in CNAME we go via */
- adns_qf_cname_loose= 0x00000100, /* allow refs to CNAMEs - without, get _s_cname */
- adns_qf_cname_forbid= 0x00000200, /* don't follow CNAMEs, instead give _s_cname */
- adns__qf_internalmask= 0x0ff00000
-} adns_queryflags;
-
-typedef enum {
- adns__rrt_typemask= 0x0ffff,
- adns__qtf_deref= 0x10000, /* dereference domains and perhaps produce extra data */
- adns__qtf_mail822= 0x20000, /* make mailboxes be in RFC822 rcpt field format */
-
- adns_r_none= 0,
-
- adns_r_a= 1,
-
- adns_r_ns_raw= 2,
- adns_r_ns= adns_r_ns_raw|adns__qtf_deref,
-
- adns_r_cname= 5,
-
- adns_r_soa_raw= 6,
- adns_r_soa= adns_r_soa_raw|adns__qtf_mail822,
-
- adns_r_ptr_raw= 12,
- adns_r_ptr= adns_r_ptr_raw|adns__qtf_deref,
-
- adns_r_hinfo= 13,
-
- adns_r_mx_raw= 15,
- adns_r_mx= adns_r_mx_raw|adns__qtf_deref,
-
- adns_r_txt= 16,
-
- adns_r_rp_raw= 17,
- adns_r_rp= adns_r_rp_raw|adns__qtf_mail822,
-
- adns_r_addr= adns_r_a|adns__qtf_deref
-
-} adns_rrtype;
-
-/*
- * In queries without qf_quoteok_*, all domains must have standard
- * legal syntax, or you get adns_s_querydomainvalid (if the query
- * domain contains bad characters) or adns_s_answerdomaininvalid (if
- * the answer contains bad characters).
- *
- * In queries _with_ qf_quoteok_*, domains in the query or response
- * may contain any characters, quoted according to RFC1035 5.1. On
- * input to adns, the char* is a pointer to the interior of a "
- * delimited string, except that " may appear in it, and on output,
- * the char* is a pointer to a string which would be legal either
- * inside or outside " delimiters, and any characters not usually
- * legal in domain names will be quoted as \X (if the character is
- * 33-126 except \ and ") or \DDD.
- *
- * If the query goes via a CNAME then the canonical name (ie, the
- * thing that the CNAME record refers to) is usually allowed to
- * contain any characters, which will be quoted as above. With
- * adns_qf_quotefail_cname you get adns_s_answerdomaininvalid when
- * this happens. (This is a change from version 0.4 and earlier, in
- * which failing the query was the default, and you had to say
- * adns_qf_quoteok_cname to avoid this; that flag is now deprecated.)
- *
- * In version 0.4 and earlier, asking for _raw records containing
- * mailboxes without specifying _qf_quoteok_anshost was silly. This
- * is no longer the case. In this version only parts of responses
- * that are actually supposed to be hostnames will be refused by
- * default if quote-requiring characters are found.
- */
-
-/*
- * If you ask for an RR which contains domains which are actually
- * encoded mailboxes, and don't ask for the _raw version, then adns
- * returns the mailbox formatted suitably for an RFC822 recipient
- * header field. The particular format used is that if the mailbox
- * requires quoting according to the rules in RFC822 then the
- * local-part is quoted in double quotes, which end at the next
- * unescaped double quote. (\ is the escape char, and is doubled, and
- * is used to escape only \ and ".) Otherwise the local-part is
- * presented as-is. In any case this is followed by an @ and the
- * domain. The domain will not contain any characters not legal in
- * hostnames. adns will protect the application from local parts
- * containing control characters - these appear to be legal according
- * to RFC822 but are clearly a bad idea.
- *
- * If you ask for the domain with _raw then _no_ checking is done
- * (even on the host part, regardless of adns_qf_quoteok_anshost), and
- * you just get the domain name in master file format.
- *
- * If no mailbox is supplied the returned string will be `.' in either
- * caswe.
- */
-
-typedef enum {
- adns_s_ok,
-
- /* locally induced errors */
- adns_s_nomemory,
- adns_s_unknownrrtype,
- adns_s_systemfail,
-
- adns_s_max_localfail= 29,
-
- /* remotely induced errors, detected locally */
- adns_s_timeout,
- adns_s_allservfail,
- adns_s_norecurse,
- adns_s_invalidresponse,
- adns_s_unknownformat,
-
- adns_s_max_remotefail= 59,
-
- /* remotely induced errors, reported by remote server to us */
- adns_s_rcodeservfail,
- adns_s_rcodeformaterror,
- adns_s_rcodenotimplemented,
- adns_s_rcoderefused,
- adns_s_rcodeunknown,
-
- adns_s_max_tempfail= 99,
-
- /* remote configuration errors */
- adns_s_inconsistent, /* PTR gives domain whose A does not exist and match */
- adns_s_prohibitedcname, /* CNAME found where eg A expected (not if _qf_loosecname) */
- adns_s_answerdomaininvalid,
- adns_s_answerdomaintoolong,
- adns_s_invaliddata,
-
- adns_s_max_misconfig= 199,
-
- /* permanent problems with the query */
- adns_s_querydomainwrong,
- adns_s_querydomaininvalid,
- adns_s_querydomaintoolong,
-
- adns_s_max_misquery= 299,
-
- /* permanent errors */
- adns_s_nxdomain,
- adns_s_nodata,
-
- adns_s_max_permfail= 499
-
-} adns_status;
-
-typedef struct {
- int len;
- union {
- struct sockaddr sa;
- struct sockaddr_in inet;
- } addr;
-} adns_rr_addr;
-
-typedef struct {
- char *host;
- adns_status astatus;
- int naddrs; /* temp fail => -1, perm fail => 0, s_ok => >0 */
- adns_rr_addr *addrs;
-} adns_rr_hostaddr;
-
-typedef struct {
- char *(array[2]);
-} adns_rr_strpair;
-
-typedef struct {
- int i;
- adns_rr_hostaddr ha;
-} adns_rr_inthostaddr;
-
-typedef struct {
- /* Used both for mx_raw, in which case i is the preference and str the domain,
- * and for txt, in which case each entry has i for the `text' length,
- * and str for the data (which will have had an extra nul appended
- * so that if it was plain text it is now a null-terminated string).
- */
- int i;
- char *str;
-} adns_rr_intstr;
-
-typedef struct {
- adns_rr_intstr array[2];
-} adns_rr_intstrpair;
-
-typedef struct {
- char *mname, *rname;
- unsigned long serial, refresh, retry, expire, minimum;
-} adns_rr_soa;
-
-typedef struct {
- adns_status status;
- char *cname; /* always NULL if query was for CNAME records */
- char *owner; /* only set if requested in query flags */
- adns_rrtype type; /* guaranteed to be same as in query */
- time_t expires; /* expiry time, defined only if _s_ok, nxdomain or nodata. NOT TTL! */
- int nrrs, rrsz; /* nrrs is 0 if an error occurs */
- union {
- void *untyped;
- unsigned char *bytes;
- char *(*str); /* ns_raw, cname, ptr, ptr_raw */
- adns_rr_intstr *(*manyistr); /* txt (list of strings ends with i=-1, str=0) */
- adns_rr_addr *addr; /* addr */
- struct in_addr *inaddr; /* a */
- adns_rr_hostaddr *hostaddr; /* ns */
- adns_rr_intstrpair *intstrpair; /* hinfo */
- adns_rr_strpair *strpair; /* rp, rp_raw */
- adns_rr_inthostaddr *inthostaddr; /* mx */
- adns_rr_intstr *intstr; /* mx_raw */
- adns_rr_soa *soa; /* soa, soa_raw */
- } rrs;
-} adns_answer;
-
-/* Memory management:
- * adns_state and adns_query are actually pointers to malloc'd state;
- * On submission questions are copied, including the owner domain;
- * Answers are malloc'd as a single piece of memory; pointers in the
- * answer struct point into further memory in the answer.
- * query_io:
- * Must always be non-null pointer;
- * If *query_io is 0 to start with then any query may be returned;
- * If *query_io is !0 adns_query then only that query may be returned.
- * If the call is successful, *query_io, *answer_r, and *context_r
- * will all be set.
- * Errors:
- * Return values are 0 or an errno value.
- *
- * For _init, _init_strcfg, _submit and _synchronous, system errors
- * (eg, failure to create sockets, malloc failure, etc.) return errno
- * values.
- *
- * For _wait and _check failures are reported in the answer
- * structure, and only 0, ESRCH or (for _check) EAGAIN is
- * returned: if no (appropriate) requests are done adns_check returns
- * EAGAIN; if no (appropriate) requests are outstanding both
- * adns_query and adns_wait return ESRCH.
- *
- * Additionally, _wait can return EINTR if you set adns_if_eintr.
- *
- * All other errors (nameserver failure, timed out connections, &c)
- * are returned in the status field of the answer. After a
- * successful _wait or _check, if status is nonzero then nrrs will be
- * 0, otherwise it will be >0. type will always be the type
- * requested.
- */
-
-int adns_init(adns_state *newstate_r, adns_initflags flags,
- FILE *diagfile /*0=>stderr*/);
-
-int adns_init_strcfg(adns_state *newstate_r, adns_initflags flags,
- FILE *diagfile /*0=>discard*/, const char *configtext);
-
-/* Configuration:
- * adns_init reads /etc/resolv.conf, which is expected to be (broadly
- * speaking) in the format expected by libresolv, and then
- * /etc/resolv-adns.conf if it exists. adns_init_strcfg is instead
- * passed a string which is interpreted as if it were the contents of
- * resolv.conf or resolv-adns.conf. In general, configuration which
- * is set later overrides any that is set earlier.
- *
- * Standard directives understood in resolv[-adns].conf:
- *
- * nameserver <address>
- * Must be followed by the IP address of a nameserver. Several
- * nameservers may be specified, and they will be tried in the order
- * found. There is a compiled in limit, currently 5, on the number
- * of nameservers. (libresolv supports only 3 nameservers.)
- *
- * search <domain> ...
- * Specifies the search list for queries which specify
- * adns_qf_search. This is a list of domains to append to the query
- * domain. The query domain will be tried as-is either before all
- * of these or after them, depending on the ndots option setting
- * (see below).
- *
- * domain <domain>
- * This is present only for backward compatibility with obsolete
- * versions of libresolv. It should not be used, and is interpreted
- * by adns as if it were `search' - note that this is subtly
- * different to libresolv's interpretation of this directive.
- *
- * sortlist <addr>/<mask> ...
- * Should be followed by a sequence of IP-address and netmask pairs,
- * separated by spaces. They may be specified as
- * eg. 172.30.206.0/24 or 172.30.206.0/255.255.255.0. Currently up
- * to 15 pairs may be specified (but note that libresolv only
- * supports up to 10).
- *
- * options
- * Should followed by one or more options, separated by spaces.
- * Each option consists of an option name, followed by optionally
- * a colon and a value. Options are listed below.
- *
- * Non-standard directives understood in resolv[-adns].conf:
- *
- * clearnameservers
- * Clears the list of nameservers, so that further nameserver lines
- * start again from the beginning.
- *
- * include <filename>
- * The specified file will be read.
- *
- * Additionally, adns will ignore lines in resolv[-adns].conf which
- * start with a #.
- *
- * Standard options understood:
- *
- * debug
- * Enables debugging output from the resolver, which will be written
- * to stderr.
- *
- * ndots:<count>
- * Affects whether queries with adns_qf_search will be tried first
- * without adding domains from the searchlist, or whether the bare
- * query domain will be tried last. Queries which contain at least
- * <count> dots will be tried bare first. The default is 1.
- *
- * Non-standard options understood:
- *
- * adns_checkc:none
- * adns_checkc:entex
- * adns_checkc:freq
- * Changes the consistency checking frequency; this overrides the
- * setting of adns_if_check_entex, adns_if_check_freq, or neither,
- * in the flags passed to adns_init.
- *
- * There are a number of environment variables which can modify the
- * behaviour of adns. They take effect only if adns_init is used, and
- * the caller of adns_init can disable them using adns_if_noenv. In
- * each case there is both a FOO and an ADNS_FOO; the latter is
- * interpreted later so that it can override the former. Unless
- * otherwise stated, environment variables are interpreted after
- * resolv[-adns].conf are read, in the order they are listed here.
- *
- * RES_CONF, ADNS_RES_CONF
- * A filename, whose contets are in the format of resolv.conf.
- *
- * RES_CONF_TEXT, ADNS_RES_CONF_TEXT
- * A string in the format of resolv.conf.
- *
- * RES_OPTIONS, ADNS_RES_OPTIONS
- * These are parsed as if they appeared in the `options' line of a
- * resolv.conf. In addition to being parsed at this point in the
- * sequence, they are also parsed at the very beginning before
- * resolv.conf or any other environment variables are read, so that
- * any debug option can affect the processing of the configuration.
- *
- * LOCALDOMAIN, ADNS_LOCALDOMAIN
- * These are interpreted as if their contents appeared in a `search'
- * line in resolv.conf.
- */
-
-int adns_synchronous(adns_state ads,
- const char *owner,
- adns_rrtype type,
- adns_queryflags flags,
- adns_answer **answer_r);
-
-/* NB: if you set adns_if_noautosys then _submit and _check do not
- * make any system calls; you must use some of the asynch-io event
- * processing functions to actually get things to happen.
- */
-
-int adns_submit(adns_state ads,
- const char *owner,
- adns_rrtype type,
- adns_queryflags flags,
- void *context,
- adns_query *query_r);
-
-/* The owner should be quoted in master file format. */
-
-int adns_check(adns_state ads,
- adns_query *query_io,
- adns_answer **answer_r,
- void **context_r);
-
-int adns_wait(adns_state ads,
- adns_query *query_io,
- adns_answer **answer_r,
- void **context_r);
-
-/* same as adns_wait but uses poll(2) internally */
-int adns_wait_poll(adns_state ads,
- adns_query *query_io,
- adns_answer **answer_r,
- void **context_r);
-
-void adns_cancel(adns_query query);
-
-/* The adns_query you get back from _submit is valid (ie, can be
- * legitimately passed into adns functions) until it is returned by
- * adns_check or adns_wait, or passed to adns_cancel. After that it
- * must not be used. You can rely on it not being reused until the
- * first adns_submit or _transact call using the same adns_state after
- * it became invalid, so you may compare it for equality with other
- * query handles until you next call _query or _transact.
- *
- * _submit and _synchronous return ENOSYS if they don't understand the
- * query type.
- */
-
-int adns_submit_reverse(adns_state ads,
- const struct sockaddr *addr,
- adns_rrtype type,
- adns_queryflags flags,
- void *context,
- adns_query *query_r);
-/* type must be _r_ptr or _r_ptr_raw. _qf_search is ignored.
- * addr->sa_family must be AF_INET or you get ENOSYS.
- */
-
-void adns_finish(adns_state ads);
-/* You may call this even if you have queries outstanding;
- * they will be cancelled.
- */
-
-
-void adns_forallqueries_begin(adns_state ads);
-adns_query adns_forallqueries_next(adns_state ads, void **context_r);
-/* Iterator functions, which you can use to loop over the outstanding
- * (submitted but not yet successfuly checked/waited) queries.
- *
- * You can only have one iteration going at once. You may call _begin
- * at any time; after that, an iteration will be in progress. You may
- * only call _next when an iteration is in progress - anything else
- * may coredump. The iteration remains in progress until _next
- * returns 0, indicating that all the queries have been walked over,
- * or ANY other adns function is called with the same adns_state (or a
- * query in the same adns_state). There is no need to explicitly
- * finish an iteration.
- *
- * context_r may be 0. *context_r may not be set when _next returns 0.
- */
-
-void adns_checkconsistency(adns_state ads, adns_query qu);
-/* Checks the consistency of adns's internal data structures.
- * If any error is found, the program will abort().
- * You may pass 0 for qu; if you pass non-null then additional checks
- * are done to make sure that qu is a valid query.
- */
-
-/*
- * Example expected/legal calling sequence for submit/check/wait:
- * adns_init
- * adns_submit 1
- * adns_submit 2
- * adns_submit 3
- * adns_wait 1
- * adns_check 3 -> EAGAIN
- * adns_wait 2
- * adns_wait 3
- * ....
- * adns_finish
- */
-
-/*
- * Entrypoints for generic asynch io:
- * (these entrypoints are not very useful except in combination with *
- * some of the other I/O model calls which can tell you which fds to
- * be interested in):
- *
- * Note that any adns call may cause adns to open and close fds, so
- * you must call beforeselect or beforepoll again just before
- * blocking, or you may not have an up-to-date list of it's fds.
- */
-
-int adns_processany(adns_state ads);
-/* Gives adns flow-of-control for a bit. This will never block, and
- * can be used with any threading/asynch-io model. If some error
- * occurred which might cause an event loop to spin then the errno
- * value is returned.
- */
-
-int adns_processreadable(adns_state ads, int fd, const struct timeval *now);
-int adns_processwriteable(adns_state ads, int fd, const struct timeval *now);
-int adns_processexceptional(adns_state ads, int fd, const struct timeval *now);
-/* Gives adns flow-of-control so that it can process incoming data
- * from, or send outgoing data via, fd. Very like _processany. If it
- * returns zero then fd will no longer be readable or writeable
- * (unless of course more data has arrived since). adns will _only_
- * use that fd and only in the manner specified, regardless of whether
- * adns_if_noautosys was specified.
- *
- * adns_processexceptional should be called when select(2) reports an
- * exceptional condition, or poll(2) reports POLLPRI.
- *
- * It is fine to call _processreabable or _processwriteable when the
- * fd is not ready, or with an fd that doesn't belong to adns; it will
- * then just return 0.
- *
- * If some error occurred which might prevent an event loop to spin
- * then the errno value is returned.
- */
-
-void adns_processtimeouts(adns_state ads, const struct timeval *now);
-/* Gives adns flow-of-control so that it can process any timeouts
- * which might have happened. Very like _processreadable/writeable.
- *
- * now may be 0; if it isn't, *now must be the current time, recently
- * obtained from gettimeofday.
- */
-
-void adns_firsttimeout(adns_state ads,
- struct timeval **tv_mod, struct timeval *tv_buf,
- struct timeval now);
-/* Asks adns when it would first like the opportunity to time
- * something out. now must be the current time, from gettimeofday.
- *
- * If tv_mod points to 0 then tv_buf must be non-null, and
- * _firsttimeout will fill in *tv_buf with the time until the first
- * timeout, and make *tv_mod point to tv_buf. If adns doesn't have
- * anything that might need timing out it will leave *tv_mod as 0.
- *
- * If *tv_mod is not 0 then tv_buf is not used. adns will update
- * *tv_mod if it has any earlier timeout, and leave it alone if it
- * doesn't.
- *
- * This call will not actually do any I/O, or change the fds that adns
- * is using. It always succeeds and never blocks.
- */
-
-void adns_globalsystemfailure(adns_state ads);
-/* If serious problem(s) happen which globally affect your ability to
- * interact properly with adns, or adns's ability to function
- * properly, you or adns can call this function.
- *
- * All currently outstanding queries will be made to fail with
- * adns_s_systemfail, and adns will close any stream sockets it has
- * open.
- *
- * This is used by adns, for example, if gettimeofday() fails.
- * Without this the program's event loop might start to spin !
- *
- * This call will never block.
- */
-
-/*
- * Entrypoints for select-loop based asynch io:
- */
-
-void adns_beforeselect(adns_state ads, int *maxfd, fd_set *readfds,
- fd_set *writefds, fd_set *exceptfds,
- struct timeval **tv_mod, struct timeval *tv_buf,
- const struct timeval *now);
-/* Find out file descriptors adns is interested in, and when it would
- * like the opportunity to time something out. If you do not plan to
- * block then tv_mod may be 0. Otherwise, tv_mod and tv_buf are as
- * for adns_firsttimeout. readfds, writefds, exceptfds and maxfd_io may
- * not be 0.
- *
- * If *now is not 0 then this will never actually do any I/O, or
- * change the fds that adns is using or the timeouts it wants. In any
- * case it won't block.
- */
-
-void adns_afterselect(adns_state ads, int maxfd, const fd_set *readfds,
- const fd_set *writefds, const fd_set *exceptfds,
- const struct timeval *now);
-/* Gives adns flow-of-control for a bit; intended for use after
- * select. This is just a fancy way of calling adns_processreadable/
- * writeable/timeouts as appropriate, as if select had returned the
- * data being passed. Always succeeds.
- */
-
-/*
- * Example calling sequence:
- *
- * adns_init _noautosys
- * loop {
- * adns_beforeselect
- * select
- * adns_afterselect
- * ...
- * adns_submit / adns_check
- * ...
- * }
- */
-
-/*
- * Entrypoints for poll-loop based asynch io:
- */
-
-struct pollfd;
-/* In case your system doesn't have it or you forgot to include
- * <sys/poll.h>, to stop the following declarations from causing
- * problems. If your system doesn't have poll then the following
- * entrypoints will not be defined in libadns. Sorry !
- */
-
-int adns_beforepoll(adns_state ads, struct pollfd *fds, int *nfds_io, int *timeout_io,
- const struct timeval *now);
-/* Finds out which fd's adns is interested in, and when it would like
- * to be able to time things out. This is in a form suitable for use
- * with poll(2).
- *
- * On entry, usually fds should point to at least *nfds_io structs.
- * adns will fill up to that many structs will information for poll,
- * and record in *nfds_io how many structs it filled. If it wants to
- * listen for more structs then *nfds_io will be set to the number
- * required and _beforepoll will return ERANGE.
- *
- * You may call _beforepoll with fds==0 and *nfds_io 0, in which case
- * adns will fill in the number of fds that it might be interested in
- * in *nfds_io, and always return either 0 (if it is not interested in
- * any fds) or ERANGE (if it is).
- *
- * NOTE that (unless now is 0) adns may acquire additional fds
- * from one call to the next, so you must put adns_beforepoll in a
- * loop, rather than assuming that the second call (with the buffer
- * size requested by the first) will not return ERANGE.
- *
- * adns only ever sets POLLIN, POLLOUT and POLLPRI in its pollfd
- * structs, and only ever looks at those bits. POLLPRI is required to
- * detect TCP Urgent Data (which should not be used by a DNS server)
- * so that adns can know that the TCP stream is now useless.
- *
- * In any case, *timeout_io should be a timeout value as for poll(2),
- * which adns will modify downwards as required. If the caller does
- * not plan to block then *timeout_io should be 0 on entry, or
- * alternatively, timeout_io may be 0. (Alternatively, the caller may
- * use _beforeselect with timeout_io==0 to find out about file
- * descriptors, and use _firsttimeout is used to find out when adns
- * might want to time something out.)
- *
- * adns_beforepoll will return 0 on success, and will not fail for any
- * reason other than the fds buffer being too small (ERANGE).
- *
- * This call will never actually do any I/O. If you supply the
- * current time it will not change the fds that adns is using or the
- * timeouts it wants.
- *
- * In any case this call won't block.
- */
-
-#define ADNS_POLLFDS_RECOMMENDED 2
-/* If you allocate an fds buf with at least RECOMMENDED entries then
- * you are unlikely to need to enlarge it. You are recommended to do
- * so if it's convenient. However, you must be prepared for adns to
- * require more space than this.
- */
-
-void adns_afterpoll(adns_state ads, const struct pollfd *fds, int nfds,
- const struct timeval *now);
-/* Gives adns flow-of-control for a bit; intended for use after
- * poll(2). fds and nfds should be the results from poll(). pollfd
- * structs mentioning fds not belonging to adns will be ignored.
- */
-
-
-adns_status adns_rr_info(adns_rrtype type,
- const char **rrtname_r, const char **fmtname_r,
- int *len_r,
- const void *datap, char **data_r);
-/*
- * Get information about a query type, or convert reply data to a
- * textual form. type must be specified, and the official name of the
- * corresponding RR type will be returned in *rrtname_r, and
- * information about the processing style in *fmtname_r. The length
- * of the table entry in an answer for that type will be returned in
- * in *len_r. Any or all of rrtname_r, fmtname_r and len_r may be 0.
- * If fmtname_r is non-null then *fmtname_r may be null on return,
- * indicating that no special processing is involved.
- *
- * data_r be must be non-null iff datap is. In this case *data_r will
- * be set to point to a string pointing to a representation of the RR
- * data in master file format. (The owner name, timeout, class and
- * type will not be present - only the data part of the RR.) The
- * memory will have been obtained from malloc() and must be freed by
- * the caller.
- *
- * Usually this routine will succeed. Possible errors include:
- * adns_s_nomemory
- * adns_s_rrtypeunknown
- * adns_s_invaliddata (*datap contained garbage)
- * If an error occurs then no memory has been allocated,
- * and *rrtname_r, *fmtname_r, *len_r and *data_r are undefined.
- *
- * There are some adns-invented data formats which are not official
- * master file formats. These include:
- *
- * Mailboxes if __qtf_mail822: these are just included as-is.
- *
- * Addresses (adns_rr_addr): these may be of pretty much any type.
- * The representation is in two parts: first, a word for the address
- * family (ie, in AF_XXX, the XXX), and then one or more items for the
- * address itself, depending on the format. For an IPv4 address the
- * syntax is INET followed by the dotted quad (from inet_ntoa).
- * Currently only IPv4 is supported.
- *
- * Text strings (as in adns_rr_txt) appear inside double quotes, and
- * use \" and \\ to represent " and \, and \xHH to represent
- * characters not in the range 32-126.
- *
- * Hostname with addresses (adns_rr_hostaddr): this consists of the
- * hostname, as usual, followed by the adns_status value, as an
- * abbreviation, and then a descriptive string (encoded as if it were
- * a piece of text), for the address lookup, followed by zero or more
- * addresses enclosed in ( and ). If the result was a permanent
- * failure, then a single ? appears instead of the ( ). If the
- * result was a temporary failure then an empty pair of parentheses
- * appears (which a space in between). For example, one of the NS
- * records for greenend.org.uk comes out like
- * ns.chiark.greenend.org.uk ok "OK" ( INET 195.224.76.132 )
- * an MX referring to a nonexistent host might come out like:
- * 50 sun2.nsfnet-relay.ac.uk nxdomain "No such domain" ( )
- * and if nameserver information is not available you might get:
- * dns2.spong.dyn.ml.org timeout "DNS query timed out" ?
- */
-
-const char *adns_strerror(adns_status st);
-const char *adns_errabbrev(adns_status st);
-const char *adns_errtypeabbrev(adns_status st);
-/* Like strerror but for adns_status values. adns_errabbrev returns
- * the abbreviation of the error - eg, for adns_s_timeout it returns
- * "timeout". adns_errtypeabbrev returns the abbreviation of the
- * error class: ie, for values up to adns_s_max_XXX it will return the
- * string XXX. You MUST NOT call these functions with status values
- * not returned by the same adns library.
- */
-
-#ifdef __cplusplus
-} /* end of extern "C" */
-#endif
-#endif
diff --git a/adns-0.6/src/adns.make b/adns-0.6/src/adns.make
deleted file mode 100644
index d468075..0000000
--- a/adns-0.6/src/adns.make
+++ /dev/null
@@ -1,25 +0,0 @@
-# src/adns.make - library definitions, including list of object files
-#
-# This file is
-# Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
-#
-# It is part of adns, which is
-# Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
-# Copyright (C) 1999 Tony Finch <dot@dotat.at>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-LIBOBJS= types.o event.o query.o reply.o general.o setup.o transmit.o \
- parse.o poll.o check.o
diff --git a/adns-0.6/src/check.c b/adns-0.6/src/check.c
deleted file mode 100644
index f0f1eec..0000000
--- a/adns-0.6/src/check.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * check.c
- * - consistency checks
- */
-/*
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "internal.h"
-
-void adns_checkconsistency(adns_state ads, adns_query qu) {
- adns__consistency(ads,qu,cc_user);
-}
-
-#define DLIST_CHECK(list, nodevar, part, body) \
- if ((list).head) { \
- assert(! (list).head->part back); \
- for ((nodevar)= (list).head; (nodevar); (nodevar)= (nodevar)->part next) { \
- assert((nodevar)->part next \
- ? (nodevar) == (nodevar)->part next->part back \
- : (nodevar) == (list).tail); \
- body \
- } \
- }
-
-#define DLIST_ASSERTON(node, nodevar, list, part) \
- do { \
- for ((nodevar)= (list).head; \
- (nodevar) != (node); \
- (nodevar)= (nodevar)->part next) { \
- assert((nodevar)); \
- } \
- } while(0)
-
-static void checkc_query_alloc(adns_state ads, adns_query qu) {
- allocnode *an;
-
- DLIST_CHECK(qu->allocations, an, , {
- });
-}
-
-static void checkc_query(adns_state ads, adns_query qu) {
- adns_query child;
-
- assert(qu->udpnextserver < ads->nservers);
- assert(!(qu->udpsent & (~0UL << ads->nservers)));
- assert(qu->search_pos <= ads->nsearchlist);
- if (qu->parent) DLIST_ASSERTON(qu, child, qu->parent->children, siblings.);
-}
-
-static void checkc_notcpbuf(adns_state ads) {
- assert(!ads->tcpsend.used);
- assert(!ads->tcprecv.used);
- assert(!ads->tcprecv_skip);
-}
-
-static void checkc_global(adns_state ads) {
- int i;
-
- assert(ads->udpsocket >= 0);
-
- for (i=0; i<ads->nsortlist; i++)
- assert(!(ads->sortlist[i].base.s_addr & ~ads->sortlist[i].mask.s_addr));
-
- assert(ads->tcpserver >= 0 && ads->tcpserver < ads->nservers);
-
- switch (ads->tcpstate) {
- case server_connecting:
- assert(ads->tcpsocket >= 0);
- checkc_notcpbuf(ads);
- break;
- case server_disconnected:
- case server_broken:
- assert(ads->tcpsocket == -1);
- checkc_notcpbuf(ads);
- break;
- case server_ok:
- assert(ads->tcpsocket >= 0);
- assert(ads->tcprecv_skip <= ads->tcprecv.used);
- break;
- default:
- assert(!"ads->tcpstate value");
- }
-
- assert(ads->searchlist || !ads->nsearchlist);
-}
-
-static void checkc_queue_udpw(adns_state ads) {
- adns_query qu;
-
- DLIST_CHECK(ads->udpw, qu, , {
- assert(qu->state==query_tosend);
- assert(qu->retries <= UDPMAXRETRIES);
- assert(qu->udpsent);
- assert(!qu->children.head && !qu->children.tail);
- checkc_query(ads,qu);
- checkc_query_alloc(ads,qu);
- });
-}
-
-static void checkc_queue_tcpw(adns_state ads) {
- adns_query qu;
-
- DLIST_CHECK(ads->tcpw, qu, , {
- assert(qu->state==query_tcpw);
- assert(!qu->children.head && !qu->children.tail);
- assert(qu->retries <= ads->nservers+1);
- checkc_query(ads,qu);
- checkc_query_alloc(ads,qu);
- });
-}
-
-static void checkc_queue_childw(adns_state ads) {
- adns_query parent, child;
-
- DLIST_CHECK(ads->childw, parent, , {
- assert(parent->state == query_childw);
- assert(parent->children.head);
- DLIST_CHECK(parent->children, child, siblings., {
- assert(child->parent == parent);
- assert(child->state != query_done);
- });
- checkc_query(ads,parent);
- checkc_query_alloc(ads,parent);
- });
-}
-
-static void checkc_queue_output(adns_state ads) {
- adns_query qu;
-
- DLIST_CHECK(ads->output, qu, , {
- assert(qu->state == query_done);
- assert(!qu->children.head && !qu->children.tail);
- assert(!qu->parent);
- assert(!qu->allocations.head && !qu->allocations.tail);
- checkc_query(ads,qu);
- });
-}
-
-void adns__consistency(adns_state ads, adns_query qu, consistency_checks cc) {
- adns_query search;
-
- switch (cc) {
- case cc_user:
- break;
- case cc_entex:
- if (!(ads->iflags & adns_if_checkc_entex)) return;
- break;
- case cc_freq:
- if ((ads->iflags & adns_if_checkc_freq) != adns_if_checkc_freq) return;
- break;
- default:
- abort();
- }
-
- checkc_global(ads);
- checkc_queue_udpw(ads);
- checkc_queue_tcpw(ads);
- checkc_queue_childw(ads);
- checkc_queue_output(ads);
-
- if (qu) {
- switch (qu->state) {
- case query_tosend:
- DLIST_ASSERTON(qu, search, ads->udpw, );
- break;
- case query_tcpw:
- DLIST_ASSERTON(qu, search, ads->tcpw, );
- break;
- case query_childw:
- DLIST_ASSERTON(qu, search, ads->childw, );
- break;
- case query_done:
- DLIST_ASSERTON(qu, search, ads->output, );
- break;
- default:
- assert(!"specific query state");
- }
- }
-}
diff --git a/adns-0.6/src/config.h.in b/adns-0.6/src/config.h.in
deleted file mode 100644
index 93a4ad8..0000000
--- a/adns-0.6/src/config.h.in
+++ /dev/null
@@ -1,91 +0,0 @@
-/* src/config.h.in. Generated automatically from configure.in by autoheader. */
-
-/* Define if function attributes a la GCC 2.5 and higher are available. */
-#undef HAVE_GNUC25_ATTRIB
-
-/* Define if constant functions a la GCC 2.5 and higher are available. */
-#undef HAVE_GNUC25_CONST
-
-/* Define if nonreturning functions a la GCC 2.5 and higher are available. */
-#undef HAVE_GNUC25_NORETURN
-
-/* Define if printf-format argument lists a la GCC are available. */
-#undef HAVE_GNUC25_PRINTFFORMAT
-
-/* Define if we want to include rpc/types.h. Crap BSDs put INADDR_LOOPBACK there. */
-#undef HAVEUSE_RPCTYPES_H
-
-/* Define if you have the poll function. */
-#undef HAVE_POLL
-
-/* Define if you have the nsl library (-lnsl). */
-#undef HAVE_LIBNSL
-
-/* Define if you have the socket library (-lsocket). */
-#undef HAVE_LIBSOCKET
-
-/* Use the definitions: */
-
-#ifdef HAVE_POLL
-#include <sys/poll.h>
-#else
-/* kludge it up */
-struct pollfd { int fd; short events; short revents; };
-#define POLLIN 1
-#define POLLPRI 2
-#define POLLOUT 4
-#endif
-
-/* GNU C attributes. */
-#ifndef FUNCATTR
-#ifdef HAVE_GNUC25_ATTRIB
-#define FUNCATTR(x) __attribute__(x)
-#else
-#define FUNCATTR(x)
-#endif
-#endif
-
-/* GNU C printf formats, or null. */
-#ifndef ATTRPRINTF
-#ifdef HAVE_GNUC25_PRINTFFORMAT
-#define ATTRPRINTF(si,tc) format(printf,si,tc)
-#else
-#define ATTRPRINTF(si,tc)
-#endif
-#endif
-#ifndef PRINTFFORMAT
-#define PRINTFFORMAT(si,tc) FUNCATTR((ATTRPRINTF(si,tc)))
-#endif
-
-/* GNU C nonreturning functions, or null. */
-#ifndef ATTRNORETURN
-#ifdef HAVE_GNUC25_NORETURN
-#define ATTRNORETURN noreturn
-#else
-#define ATTRNORETURN
-#endif
-#endif
-#ifndef NONRETURNING
-#define NONRETURNING FUNCATTR((ATTRNORETURN))
-#endif
-
-/* Combination of both the above. */
-#ifndef NONRETURNPRINTFFORMAT
-#define NONRETURNPRINTFFORMAT(si,tc) FUNCATTR((ATTRPRINTF(si,tc),ATTRNORETURN))
-#endif
-
-/* GNU C constant functions, or null. */
-#ifndef ATTRCONST
-#ifdef HAVE_GNUC25_CONST
-#define ATTRCONST const
-#else
-#define ATTRCONST
-#endif
-#endif
-#ifndef CONSTANT
-#define CONSTANT FUNCATTR((ATTRCONST))
-#endif
-
-#ifdef HAVEUSE_RPCTYPES_H
-#include <rpc/types.h>
-#endif
diff --git a/adns-0.6/src/dlist.h b/adns-0.6/src/dlist.h
deleted file mode 100644
index de0268f..0000000
--- a/adns-0.6/src/dlist.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * dlist.h
- * - macros for handling doubly linked lists
- */
-/*
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef ADNS_DLIST_H_INCLUDED
-#define ADNS_DLIST_H_INCLUDED
-
-#define LIST_INIT(list) ((list).head= (list).tail= 0)
-#define LINK_INIT(link) ((link).next= (link).back= 0)
-
-#define LIST_UNLINK_PART(list,node,part) \
- do { \
- if ((node)->part back) (node)->part back->part next= (node)->part next; \
- else (list).head= (node)->part next; \
- if ((node)->part next) (node)->part next->part back= (node)->part back; \
- else (list).tail= (node)->part back; \
- } while(0)
-
-#define LIST_LINK_TAIL_PART(list,node,part) \
- do { \
- (node)->part next= 0; \
- (node)->part back= (list).tail; \
- if ((list).tail) (list).tail->part next= (node); else (list).head= (node); \
- (list).tail= (node); \
- } while(0)
-
-#define LIST_UNLINK(list,node) LIST_UNLINK_PART(list,node,)
-#define LIST_LINK_TAIL(list,node) LIST_LINK_TAIL_PART(list,node,)
-
-#endif
diff --git a/adns-0.6/src/event.c b/adns-0.6/src/event.c
deleted file mode 100644
index a1641c6..0000000
--- a/adns-0.6/src/event.c
+++ /dev/null
@@ -1,699 +0,0 @@
-/*
- * event.c
- * - event loop core
- * - TCP connection management
- * - user-visible check/wait and event-loop-related functions
- */
-/*
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "internal.h"
-#include "tvarith.h"
-
-/* TCP connection management. */
-
-static void tcp_close(adns_state ads) {
- int serv;
-
- serv= ads->tcpserver;
- close(ads->tcpsocket);
- ads->tcpsocket= -1;
- ads->tcprecv.used= ads->tcprecv_skip= ads->tcpsend.used= 0;
-}
-
-void adns__tcp_broken(adns_state ads, const char *what, const char *why) {
- int serv;
-
- assert(ads->tcpstate == server_connecting || ads->tcpstate == server_ok);
- serv= ads->tcpserver;
- if (what) adns__warn(ads,serv,0,"TCP connection failed: %s: %s",what,why);
-
- tcp_close(ads);
- ads->tcpstate= server_broken;
- ads->tcpserver= (serv+1)%ads->nservers;
-}
-
-static void tcp_connected(adns_state ads, struct timeval now) {
- adns_query qu, nqu;
-
- adns__debug(ads,ads->tcpserver,0,"TCP connected");
- ads->tcpstate= server_ok;
- for (qu= ads->tcpw.head; qu && ads->tcpstate == server_ok; qu= nqu) {
- nqu= qu->next;
- assert(qu->state == query_tcpw);
- adns__querysend_tcp(qu,now);
- }
-}
-
-void adns__tcp_tryconnect(adns_state ads, struct timeval now) {
- int r, fd, tries;
- struct sockaddr_in addr;
- struct protoent *proto;
-
- for (tries=0; tries<ads->nservers; tries++) {
- switch (ads->tcpstate) {
- case server_connecting:
- case server_ok:
- case server_broken:
- return;
- case server_disconnected:
- break;
- default:
- abort();
- }
-
- assert(!ads->tcpsend.used);
- assert(!ads->tcprecv.used);
- assert(!ads->tcprecv_skip);
-
- proto= getprotobyname("tcp");
- if (!proto) { adns__diag(ads,-1,0,"unable to find protocol no. for TCP !"); return; }
- fd= socket(AF_INET,SOCK_STREAM,proto->p_proto);
- if (fd<0) {
- adns__diag(ads,-1,0,"cannot create TCP socket: %s",strerror(errno));
- return;
- }
- r= adns__setnonblock(ads,fd);
- if (r) {
- adns__diag(ads,-1,0,"cannot make TCP socket nonblocking: %s",strerror(r));
- close(fd);
- return;
- }
- memset(&addr,0,sizeof(addr));
- addr.sin_family= AF_INET;
- addr.sin_port= htons(DNS_PORT);
- addr.sin_addr= ads->servers[ads->tcpserver].addr;
- r= connect(fd,(const struct sockaddr*)&addr,sizeof(addr));
- ads->tcpsocket= fd;
- ads->tcpstate= server_connecting;
- if (r==0) { tcp_connected(ads,now); return; }
- if (errno == EWOULDBLOCK || errno == EINPROGRESS) {
- ads->tcptimeout= now;
- timevaladd(&ads->tcptimeout,TCPCONNMS);
- return;
- }
- adns__tcp_broken(ads,"connect",strerror(errno));
- ads->tcpstate= server_disconnected;
- }
-}
-
-/* Timeout handling functions. */
-
-void adns__must_gettimeofday(adns_state ads, const struct timeval **now_io,
- struct timeval *tv_buf) {
- const struct timeval *now;
- int r;
-
- now= *now_io;
- if (now) return;
- r= gettimeofday(tv_buf,0); if (!r) { *now_io= tv_buf; return; }
- adns__diag(ads,-1,0,"gettimeofday failed: %s",strerror(errno));
- adns_globalsystemfailure(ads);
- return;
-}
-
-static void inter_maxto(struct timeval **tv_io, struct timeval *tvbuf,
- struct timeval maxto) {
- struct timeval *rbuf;
-
- if (!tv_io) return;
- rbuf= *tv_io;
- if (!rbuf) {
- *tvbuf= maxto; *tv_io= tvbuf;
- } else {
- if (timercmp(rbuf,&maxto,>)) *rbuf= maxto;
- }
-/*fprintf(stderr,"inter_maxto maxto=%ld.%06ld result=%ld.%06ld\n",
- maxto.tv_sec,maxto.tv_usec,(**tv_io).tv_sec,(**tv_io).tv_usec);*/
-}
-
-static void inter_maxtoabs(struct timeval **tv_io, struct timeval *tvbuf,
- struct timeval now, struct timeval maxtime) {
- /* tv_io may be 0 */
- ldiv_t dr;
-
-/*fprintf(stderr,"inter_maxtoabs now=%ld.%06ld maxtime=%ld.%06ld\n",
- now.tv_sec,now.tv_usec,maxtime.tv_sec,maxtime.tv_usec);*/
- if (!tv_io) return;
- maxtime.tv_sec -= (now.tv_sec+2);
- maxtime.tv_usec -= (now.tv_usec-2000000);
- dr= ldiv(maxtime.tv_usec,1000000);
- maxtime.tv_sec += dr.quot;
- maxtime.tv_usec -= dr.quot*1000000;
- if (maxtime.tv_sec<0) timerclear(&maxtime);
- inter_maxto(tv_io,tvbuf,maxtime);
-}
-
-static void timeouts_queue(adns_state ads, int act,
- struct timeval **tv_io, struct timeval *tvbuf,
- struct timeval now, struct query_queue *queue) {
- adns_query qu, nqu;
-
- for (qu= queue->head; qu; qu= nqu) {
- nqu= qu->next;
- if (!timercmp(&now,&qu->timeout,>)) {
- inter_maxtoabs(tv_io,tvbuf,now,qu->timeout);
- } else {
- if (!act) {
- tvbuf->tv_sec= 0;
- tvbuf->tv_usec= 0;
- *tv_io= tvbuf;
- return;
- }
- LIST_UNLINK(*queue,qu);
- if (qu->state != query_tosend) {
- adns__query_fail(qu,adns_s_timeout);
- } else {
- adns__query_send(qu,now);
- }
- nqu= queue->head;
- }
- }
-}
-
-static void tcp_events(adns_state ads, int act,
- struct timeval **tv_io, struct timeval *tvbuf,
- struct timeval now) {
- adns_query qu, nqu;
-
- for (;;) {
- switch (ads->tcpstate) {
- case server_broken:
- for (qu= ads->tcpw.head; qu; qu= nqu) {
- nqu= qu->next;
- assert(qu->state == query_tcpw);
- if (qu->retries > ads->nservers) {
- LIST_UNLINK(ads->tcpw,qu);
- adns__query_fail(qu,adns_s_allservfail);
- }
- }
- ads->tcpstate= server_disconnected;
- case server_disconnected: /* fall through */
- if (!ads->tcpw.head) return;
- adns__tcp_tryconnect(ads,now);
- break;
- case server_ok:
- if (ads->tcpw.head) return;
- if (!ads->tcptimeout.tv_sec) {
- assert(!ads->tcptimeout.tv_usec);
- ads->tcptimeout= now;
- timevaladd(&ads->tcptimeout,TCPIDLEMS);
- }
- case server_connecting: /* fall through */
- if (!timercmp(&now,&ads->tcptimeout,>)) {
- inter_maxtoabs(tv_io,tvbuf,now,ads->tcptimeout);
- return;
- } {
- /* TCP timeout has happened */
- switch (ads->tcpstate) {
- case server_connecting: /* failed to connect */
- adns__tcp_broken(ads,"unable to make connection","timed out");
- break;
- case server_ok: /* idle timeout */
- tcp_close(ads);
- ads->tcpstate= server_disconnected;
- return;
- default:
- abort();
- }
- }
- break;
- default:
- abort();
- }
- }
-}
-
-void adns__timeouts(adns_state ads, int act,
- struct timeval **tv_io, struct timeval *tvbuf,
- struct timeval now) {
- timeouts_queue(ads,act,tv_io,tvbuf,now, &ads->udpw);
- timeouts_queue(ads,act,tv_io,tvbuf,now, &ads->tcpw);
- tcp_events(ads,act,tv_io,tvbuf,now);
-}
-
-void adns_firsttimeout(adns_state ads,
- struct timeval **tv_io, struct timeval *tvbuf,
- struct timeval now) {
- adns__consistency(ads,0,cc_entex);
- adns__timeouts(ads, 0, tv_io,tvbuf, now);
- adns__consistency(ads,0,cc_entex);
-}
-
-void adns_processtimeouts(adns_state ads, const struct timeval *now) {
- struct timeval tv_buf;
-
- adns__consistency(ads,0,cc_entex);
- adns__must_gettimeofday(ads,&now,&tv_buf);
- if (now) adns__timeouts(ads, 1, 0,0, *now);
- adns__consistency(ads,0,cc_entex);
-}
-
-/* fd handling functions. These are the top-level of the real work of
- * reception and often transmission.
- */
-
-int adns__pollfds(adns_state ads, struct pollfd pollfds_buf[MAX_POLLFDS]) {
- /* Returns the number of entries filled in. Always zeroes revents. */
-
- assert(MAX_POLLFDS==2);
-
- pollfds_buf[0].fd= ads->udpsocket;
- pollfds_buf[0].events= POLLIN;
- pollfds_buf[0].revents= 0;
-
- switch (ads->tcpstate) {
- case server_disconnected:
- return 1;
- case server_connecting:
- pollfds_buf[1].events= POLLOUT;
- break;
- case server_ok:
- pollfds_buf[1].events= ads->tcpsend.used ? POLLIN|POLLOUT|POLLPRI : POLLIN|POLLPRI;
- break;
- default:
- abort();
- }
- pollfds_buf[1].fd= ads->tcpsocket;
- return 2;
-}
-
-int adns_processreadable(adns_state ads, int fd, const struct timeval *now) {
- int want, dgramlen, r, udpaddrlen, serv, old_skip;
- byte udpbuf[DNS_MAXUDP];
- struct sockaddr_in udpaddr;
-
- adns__consistency(ads,0,cc_entex);
-
- switch (ads->tcpstate) {
- case server_disconnected:
- case server_connecting:
- break;
- case server_ok:
- if (fd != ads->tcpsocket) break;
- assert(!ads->tcprecv_skip);
- for (;;) {
- if (ads->tcprecv.used >= ads->tcprecv_skip+2) {
- dgramlen= ((ads->tcprecv.buf[ads->tcprecv_skip]<<8) |
- ads->tcprecv.buf[ads->tcprecv_skip+1]);
- if (ads->tcprecv.used >= ads->tcprecv_skip+2+dgramlen) {
- old_skip= ads->tcprecv_skip;
- ads->tcprecv_skip += 2+dgramlen;
- adns__procdgram(ads, ads->tcprecv.buf+old_skip+2,
- dgramlen, ads->tcpserver, 1,*now);
- continue;
- } else {
- want= 2+dgramlen;
- }
- } else {
- want= 2;
- }
- ads->tcprecv.used -= ads->tcprecv_skip;
- memmove(ads->tcprecv.buf,ads->tcprecv.buf+ads->tcprecv_skip,ads->tcprecv.used);
- ads->tcprecv_skip= 0;
- if (!adns__vbuf_ensure(&ads->tcprecv,want)) { r= ENOMEM; goto xit; }
- assert(ads->tcprecv.used <= ads->tcprecv.avail);
- if (ads->tcprecv.used == ads->tcprecv.avail) continue;
- r= read(ads->tcpsocket,
- ads->tcprecv.buf+ads->tcprecv.used,
- ads->tcprecv.avail-ads->tcprecv.used);
- if (r>0) {
- ads->tcprecv.used+= r;
- } else {
- if (r) {
- if (errno==EAGAIN || errno==EWOULDBLOCK) { r= 0; goto xit; }
- if (errno==EINTR) continue;
- if (errno_resources(errno)) { r= errno; goto xit; }
- }
- adns__tcp_broken(ads,"read",r?strerror(errno):"closed");
- r= 0; goto xit;
- }
- } /* never reached */
- default:
- abort();
- }
- if (fd == ads->udpsocket) {
- for (;;) {
- udpaddrlen= sizeof(udpaddr);
- r= recvfrom(ads->udpsocket,udpbuf,sizeof(udpbuf),0,
- (struct sockaddr*)&udpaddr,&udpaddrlen);
- if (r<0) {
- if (errno == EAGAIN || errno == EWOULDBLOCK) { r= 0; goto xit; }
- if (errno == EINTR) continue;
- if (errno_resources(errno)) { r= errno; goto xit; }
- adns__warn(ads,-1,0,"datagram receive error: %s",strerror(errno));
- r= 0; goto xit;
- }
- if (udpaddrlen != sizeof(udpaddr)) {
- adns__diag(ads,-1,0,"datagram received with wrong address length %d"
- " (expected %d)", udpaddrlen,sizeof(udpaddr));
- continue;
- }
- if (udpaddr.sin_family != AF_INET) {
- adns__diag(ads,-1,0,"datagram received with wrong protocol family"
- " %u (expected %u)",udpaddr.sin_family,AF_INET);
- continue;
- }
- if (ntohs(udpaddr.sin_port) != DNS_PORT) {
- adns__diag(ads,-1,0,"datagram received from wrong port %u (expected %u)",
- ntohs(udpaddr.sin_port),DNS_PORT);
- continue;
- }
- for (serv= 0;
- serv < ads->nservers &&
- ads->servers[serv].addr.s_addr != udpaddr.sin_addr.s_addr;
- serv++);
- if (serv >= ads->nservers) {
- adns__warn(ads,-1,0,"datagram received from unknown nameserver %s",
- inet_ntoa(udpaddr.sin_addr));
- continue;
- }
- adns__procdgram(ads,udpbuf,r,serv,0,*now);
- }
- }
- r= 0;
-xit:
- adns__consistency(ads,0,cc_entex);
- return r;
-}
-
-int adns_processwriteable(adns_state ads, int fd, const struct timeval *now) {
- int r;
-
- adns__consistency(ads,0,cc_entex);
-
- switch (ads->tcpstate) {
- case server_disconnected:
- break;
- case server_connecting:
- if (fd != ads->tcpsocket) break;
- assert(ads->tcprecv.used==0);
- assert(ads->tcprecv_skip==0);
- for (;;) {
- if (!adns__vbuf_ensure(&ads->tcprecv,1)) { r= ENOMEM; goto xit; }
- r= read(ads->tcpsocket,&ads->tcprecv.buf,1);
- if (r==0 || (r<0 && (errno==EAGAIN || errno==EWOULDBLOCK))) {
- tcp_connected(ads,*now);
- r= 0; goto xit;
- }
- if (r>0) {
- adns__tcp_broken(ads,"connect/read","sent data before first request");
- r= 0; goto xit;
- }
- if (errno==EINTR) continue;
- if (errno_resources(errno)) { r= errno; goto xit; }
- adns__tcp_broken(ads,"connect/read",strerror(errno));
- r= 0; goto xit;
- } /* not reached */
- case server_ok:
- if (!(ads->tcpsend.used && fd == ads->tcpsocket)) break;
- for (;;) {
- adns__sigpipe_protect(ads);
- r= write(ads->tcpsocket,ads->tcpsend.buf,ads->tcpsend.used);
- adns__sigpipe_unprotect(ads);
- if (r<0) {
- if (errno==EINTR) continue;
- if (errno==EAGAIN || errno==EWOULDBLOCK) { r= 0; goto xit; }
- if (errno_resources(errno)) { r= errno; goto xit; }
- adns__tcp_broken(ads,"write",strerror(errno));
- r= 0; goto xit;
- } else if (r>0) {
- ads->tcpsend.used -= r;
- memmove(ads->tcpsend.buf,ads->tcpsend.buf+r,ads->tcpsend.used);
- }
- } /* not reached */
- default:
- abort();
- }
- r= 0;
-xit:
- adns__consistency(ads,0,cc_entex);
- return r;
-}
-
-int adns_processexceptional(adns_state ads, int fd, const struct timeval *now) {
- adns__consistency(ads,0,cc_entex);
- switch (ads->tcpstate) {
- case server_disconnected:
- break;
- case server_connecting:
- case server_ok:
- if (fd != ads->tcpsocket) break;
- adns__tcp_broken(ads,"poll/select","exceptional condition detected");
- break;
- default:
- abort();
- }
- adns__consistency(ads,0,cc_entex);
- return 0;
-}
-
-static void fd_event(adns_state ads, int fd,
- int revent, int pollflag,
- int maxfd, const fd_set *fds,
- int (*func)(adns_state, int fd, const struct timeval *now),
- struct timeval now, int *r_r) {
- int r;
-
- if (!(revent & pollflag)) return;
- if (fds && !(fd<maxfd && FD_ISSET(fd,fds))) return;
- r= func(ads,fd,&now);
- if (r) {
- if (r_r) {
- *r_r= r;
- } else {
- adns__diag(ads,-1,0,"process fd failed after select: %s",strerror(errno));
- adns_globalsystemfailure(ads);
- }
- }
-}
-
-void adns__fdevents(adns_state ads,
- const struct pollfd *pollfds, int npollfds,
- int maxfd, const fd_set *readfds,
- const fd_set *writefds, const fd_set *exceptfds,
- struct timeval now, int *r_r) {
- int i, fd, revents;
-
- for (i=0; i<npollfds; i++) {
- fd= pollfds[i].fd;
- if (fd >= maxfd) maxfd= fd+1;
- revents= pollfds[i].revents;
- fd_event(ads,fd, revents,POLLIN, maxfd,readfds, adns_processreadable,now,r_r);
- fd_event(ads,fd, revents,POLLOUT, maxfd,writefds, adns_processwriteable,now,r_r);
- fd_event(ads,fd, revents,POLLPRI, maxfd,exceptfds, adns_processexceptional,now,r_r);
- }
-}
-
-/* Wrappers for select(2). */
-
-void adns_beforeselect(adns_state ads, int *maxfd_io, fd_set *readfds_io,
- fd_set *writefds_io, fd_set *exceptfds_io,
- struct timeval **tv_mod, struct timeval *tv_tobuf,
- const struct timeval *now) {
- struct timeval tv_nowbuf;
- struct pollfd pollfds[MAX_POLLFDS];
- int i, fd, maxfd, npollfds;
-
- adns__consistency(ads,0,cc_entex);
-
- if (tv_mod && (!*tv_mod || (*tv_mod)->tv_sec || (*tv_mod)->tv_usec)) {
- /* The caller is planning to sleep. */
- adns__must_gettimeofday(ads,&now,&tv_nowbuf);
- if (!now) goto xit;
- adns__timeouts(ads, 1, tv_mod,tv_tobuf, *now);
- }
-
- npollfds= adns__pollfds(ads,pollfds);
- maxfd= *maxfd_io;
- for (i=0; i<npollfds; i++) {
- fd= pollfds[i].fd;
- if (fd >= maxfd) maxfd= fd+1;
- if (pollfds[i].events & POLLIN) FD_SET(fd,readfds_io);
- if (pollfds[i].events & POLLOUT) FD_SET(fd,writefds_io);
- if (pollfds[i].events & POLLPRI) FD_SET(fd,exceptfds_io);
- }
- *maxfd_io= maxfd;
-
-xit:
- adns__consistency(ads,0,cc_entex);
-}
-
-void adns_afterselect(adns_state ads, int maxfd, const fd_set *readfds,
- const fd_set *writefds, const fd_set *exceptfds,
- const struct timeval *now) {
- struct timeval tv_buf;
- struct pollfd pollfds[MAX_POLLFDS];
- int npollfds, i;
-
- adns__consistency(ads,0,cc_entex);
- adns__must_gettimeofday(ads,&now,&tv_buf);
- if (!now) goto xit;
- adns_processtimeouts(ads,now);
-
- npollfds= adns__pollfds(ads,pollfds);
- for (i=0; i<npollfds; i++) pollfds[i].revents= POLLIN|POLLOUT|POLLPRI;
- adns__fdevents(ads,
- pollfds,npollfds,
- maxfd,readfds,writefds,exceptfds,
- *now, 0);
-xit:
- adns__consistency(ads,0,cc_entex);
-}
-
-/* General helpful functions. */
-
-void adns_globalsystemfailure(adns_state ads) {
- adns__consistency(ads,0,cc_entex);
-
- while (ads->udpw.head) adns__query_fail(ads->udpw.head, adns_s_systemfail);
- while (ads->tcpw.head) adns__query_fail(ads->tcpw.head, adns_s_systemfail);
-
- switch (ads->tcpstate) {
- case server_connecting:
- case server_ok:
- adns__tcp_broken(ads,0,0);
- break;
- case server_disconnected:
- break;
- default:
- abort();
- }
- adns__consistency(ads,0,cc_entex);
-}
-
-int adns_processany(adns_state ads) {
- int r, i;
- struct timeval now;
- struct pollfd pollfds[MAX_POLLFDS];
- int npollfds;
-
- adns__consistency(ads,0,cc_entex);
-
- r= gettimeofday(&now,0);
- if (!r) adns_processtimeouts(ads,&now);
-
- /* We just use adns__fdevents to loop over the fd's trying them.
- * This seems more sensible than calling select, since we're most
- * likely just to want to do a read on one or two fds anyway.
- */
- npollfds= adns__pollfds(ads,pollfds);
- for (i=0; i<npollfds; i++) pollfds[i].revents= pollfds[i].events;
- adns__fdevents(ads,
- pollfds,npollfds,
- 0,0,0,0,
- now,&r);
-
- adns__consistency(ads,0,cc_entex);
- return 0;
-}
-
-void adns__autosys(adns_state ads, struct timeval now) {
- if (ads->iflags & adns_if_noautosys) return;
- adns_processany(ads);
-}
-
-int adns__internal_check(adns_state ads,
- adns_query *query_io,
- adns_answer **answer,
- void **context_r) {
- adns_query qu;
-
- qu= *query_io;
- if (!qu) {
- if (ads->output.head) {
- qu= ads->output.head;
- } else if (ads->udpw.head || ads->tcpw.head) {
- return EAGAIN;
- } else {
- return ESRCH;
- }
- } else {
- if (qu->id>=0) return EAGAIN;
- }
- LIST_UNLINK(ads->output,qu);
- *answer= qu->answer;
- if (context_r) *context_r= qu->ctx.ext;
- *query_io= qu;
- free(qu);
- return 0;
-}
-
-int adns_wait(adns_state ads,
- adns_query *query_io,
- adns_answer **answer_r,
- void **context_r) {
- int r, maxfd, rsel;
- fd_set readfds, writefds, exceptfds;
- struct timeval tvbuf, *tvp;
-
- adns__consistency(ads,*query_io,cc_entex);
- for (;;) {
- r= adns__internal_check(ads,query_io,answer_r,context_r);
- if (r != EAGAIN) break;
- maxfd= 0; tvp= 0;
- FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds);
- adns_beforeselect(ads,&maxfd,&readfds,&writefds,&exceptfds,&tvp,&tvbuf,0);
- rsel= select(maxfd,&readfds,&writefds,&exceptfds,tvp);
- if (rsel==-1) {
- if (errno == EINTR) {
- if (ads->iflags & adns_if_eintr) { r= EINTR; break; }
- } else {
- adns__diag(ads,-1,0,"select failed in wait: %s",strerror(errno));
- adns_globalsystemfailure(ads);
- }
- } else {
- assert(rsel >= 0);
- adns_afterselect(ads,maxfd,&readfds,&writefds,&exceptfds,0);
- }
- }
- adns__consistency(ads,0,cc_entex);
- return r;
-}
-
-int adns_check(adns_state ads,
- adns_query *query_io,
- adns_answer **answer_r,
- void **context_r) {
- struct timeval now;
- int r;
-
- adns__consistency(ads,*query_io,cc_entex);
- r= gettimeofday(&now,0);
- if (!r) adns__autosys(ads,now);
-
- r= adns__internal_check(ads,query_io,answer_r,context_r);
- adns__consistency(ads,0,cc_entex);
- return r;
-}
diff --git a/adns-0.6/src/general.c b/adns-0.6/src/general.c
deleted file mode 100644
index 8793762..0000000
--- a/adns-0.6/src/general.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * general.c
- * - diagnostic functions
- * - vbuf handling
- */
-/*
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "internal.h"
-
-/* Core diagnostic functions */
-
-void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
- int serv, adns_query qu, const char *fmt, va_list al) {
- const char *bef, *aft;
- vbuf vb;
-
- if (!ads->diagfile ||
- (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))))
- return;
-
- if (ads->iflags & adns_if_logpid) {
- fprintf(ads->diagfile,"adns%s [%ld]: ",pfx,(long)getpid());
- } else {
- fprintf(ads->diagfile,"adns%s: ",pfx);
- }
-
- vfprintf(ads->diagfile,fmt,al);
-
- bef= " (";
- aft= "\n";
-
- if (qu && qu->query_dgram) {
- adns__vbuf_init(&vb);
- fprintf(ads->diagfile,"%sQNAME=%s, QTYPE=%s",
- bef,
- adns__diag_domain(qu->ads,-1,0, &vb,
- qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
- qu->typei ? qu->typei->rrtname : "<unknown>");
- if (qu->typei && qu->typei->fmtname)
- fprintf(ads->diagfile,"(%s)",qu->typei->fmtname);
- bef=", "; aft=")\n";
- adns__vbuf_free(&vb);
- }
-
- if (serv>=0) {
- fprintf(ads->diagfile,"%sNS=%s",bef,inet_ntoa(ads->servers[serv].addr));
- bef=", "; aft=")\n";
- }
-
- fputs(aft,ads->diagfile);
-}
-
-void adns__debug(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
- va_list al;
-
- va_start(al,fmt);
- adns__vdiag(ads," debug",0,serv,qu,fmt,al);
- va_end(al);
-}
-
-void adns__warn(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
- va_list al;
-
- va_start(al,fmt);
- adns__vdiag(ads," warning",adns_if_noerrprint|adns_if_noserverwarn,serv,qu,fmt,al);
- va_end(al);
-}
-
-void adns__diag(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
- va_list al;
-
- va_start(al,fmt);
- adns__vdiag(ads,"",adns_if_noerrprint,serv,qu,fmt,al);
- va_end(al);
-}
-
-/* vbuf functions */
-
-void adns__vbuf_init(vbuf *vb) {
- vb->used= vb->avail= 0; vb->buf= 0;
-}
-
-int adns__vbuf_ensure(vbuf *vb, int want) {
- void *nb;
-
- if (vb->avail >= want) return 1;
- nb= realloc(vb->buf,want); if (!nb) return 0;
- vb->buf= nb;
- vb->avail= want;
- return 1;
-}
-
-void adns__vbuf_appendq(vbuf *vb, const byte *data, int len) {
- memcpy(vb->buf+vb->used,data,len);
- vb->used+= len;
-}
-
-int adns__vbuf_append(vbuf *vb, const byte *data, int len) {
- int newlen;
- void *nb;
-
- newlen= vb->used+len;
- if (vb->avail < newlen) {
- if (newlen<20) newlen= 20;
- newlen <<= 1;
- nb= realloc(vb->buf,newlen);
- if (!nb) { newlen= vb->used+len; nb= realloc(vb->buf,newlen); }
- if (!nb) return 0;
- vb->buf= nb;
- vb->avail= newlen;
- }
- adns__vbuf_appendq(vb,data,len);
- return 1;
-}
-
-int adns__vbuf_appendstr(vbuf *vb, const char *data) {
- int l;
- l= strlen(data);
- return adns__vbuf_append(vb,data,l);
-}
-
-void adns__vbuf_free(vbuf *vb) {
- free(vb->buf);
- adns__vbuf_init(vb);
-}
-
-/* Additional diagnostic functions */
-
-const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
- vbuf *vb, const byte *dgram, int dglen, int cbyte) {
- adns_status st;
-
- st= adns__parse_domain(ads,serv,qu,vb, pdf_quoteok, dgram,dglen,&cbyte,dglen);
- if (st == adns_s_nomemory) {
- return "<cannot report domain... out of memory>";
- }
- if (st) {
- vb->used= 0;
- if (!(adns__vbuf_appendstr(vb,"<bad format... ") &&
- adns__vbuf_appendstr(vb,adns_strerror(st)) &&
- adns__vbuf_appendstr(vb,">") &&
- adns__vbuf_append(vb,"",1))) {
- return "<cannot report bad format... out of memory>";
- }
- }
- if (!vb->used) {
- adns__vbuf_appendstr(vb,"<truncated ...>");
- adns__vbuf_append(vb,"",1);
- }
- return vb->buf;
-}
-
-adns_status adns_rr_info(adns_rrtype type,
- const char **rrtname_r, const char **fmtname_r,
- int *len_r,
- const void *datap, char **data_r) {
- const typeinfo *typei;
- vbuf vb;
- adns_status st;
-
- typei= adns__findtype(type);
- if (!typei) return adns_s_unknownrrtype;
-
- if (rrtname_r) *rrtname_r= typei->rrtname;
- if (fmtname_r) *fmtname_r= typei->fmtname;
- if (len_r) *len_r= typei->rrsz;
-
- if (!datap) return adns_s_ok;
-
- adns__vbuf_init(&vb);
- st= typei->convstring(&vb,datap);
- if (st) goto x_freevb;
- if (!adns__vbuf_append(&vb,"",1)) { st= adns_s_nomemory; goto x_freevb; }
- assert(strlen(vb.buf) == vb.used-1);
- *data_r= realloc(vb.buf,vb.used);
- if (!*data_r) *data_r= vb.buf;
- return adns_s_ok;
-
- x_freevb:
- adns__vbuf_free(&vb);
- return st;
-}
-
-
-#define SINFO(n,s) { adns_s_##n, #n, s }
-
-static const struct sinfo {
- adns_status st;
- const char *abbrev;
- const char *string;
-} sinfos[]= {
- SINFO( ok, "OK" ),
-
- SINFO( nomemory, "Out of memory" ),
- SINFO( unknownrrtype, "Query not implemented in DNS library" ),
- SINFO( systemfail, "General resolver or system failure" ),
-
- SINFO( timeout, "DNS query timed out" ),
- SINFO( allservfail, "All nameservers failed" ),
- SINFO( norecurse, "Recursion denied by nameserver" ),
- SINFO( invalidresponse, "Nameserver sent bad response" ),
- SINFO( unknownformat, "Nameserver used unknown format" ),
-
- SINFO( rcodeservfail, "Nameserver reports failure" ),
- SINFO( rcodeformaterror, "Query not understood by nameserver" ),
- SINFO( rcodenotimplemented, "Query not implemented by nameserver" ),
- SINFO( rcoderefused, "Query refused by nameserver" ),
- SINFO( rcodeunknown, "Nameserver sent unknown response code" ),
-
- SINFO( inconsistent, "Inconsistent resource records in DNS" ),
- SINFO( prohibitedcname, "DNS alias found where canonical name wanted" ),
- SINFO( answerdomaininvalid, "Found syntactically invalid domain name" ),
- SINFO( answerdomaintoolong, "Found overly-long domain name" ),
- SINFO( invaliddata, "Found invalid DNS data" ),
-
- SINFO( querydomainwrong, "Domain invalid for particular DNS query type" ),
- SINFO( querydomaininvalid, "Domain name is syntactically invalid" ),
- SINFO( querydomaintoolong, "Domain name is too long" ),
-
- SINFO( nxdomain, "No such domain" ),
- SINFO( nodata, "No such data" )
-};
-
-static int si_compar(const void *key, const void *elem) {
- const adns_status *st= key;
- const struct sinfo *si= elem;
-
- return *st < si->st ? -1 : *st > si->st ? 1 : 0;
-}
-
-static const struct sinfo *findsinfo(adns_status st) {
- return bsearch(&st,sinfos,sizeof(sinfos)/sizeof(*sinfos),sizeof(*sinfos),si_compar);
-}
-
-const char *adns_strerror(adns_status st) {
- const struct sinfo *si;
-
- si= findsinfo(st);
- return si->string;
-}
-
-const char *adns_errabbrev(adns_status st) {
- const struct sinfo *si;
-
- si= findsinfo(st);
- return si->abbrev;
-}
-
-
-#define STINFO(max) { adns_s_max_##max, #max }
-
-static const struct stinfo {
- adns_status stmax;
- const char *abbrev;
-} stinfos[]= {
- { adns_s_ok, "ok" },
- STINFO( localfail ),
- STINFO( remotefail ),
- STINFO( tempfail ),
- STINFO( misconfig ),
- STINFO( misquery ),
- STINFO( permfail )
-};
-
-static int sti_compar(const void *key, const void *elem) {
- const adns_status *st= key;
- const struct stinfo *sti= elem;
-
- adns_status here, min, max;
-
- here= *st;
- min= (sti==stinfos) ? 0 : sti[-1].stmax+1;
- max= sti->stmax;
-
- return here < min ? -1 : here > max ? 1 : 0;
-}
-
-const char *adns_errtypeabbrev(adns_status st) {
- const struct stinfo *sti;
-
- sti= bsearch(&st,stinfos,sizeof(stinfos)/sizeof(*stinfos),sizeof(*stinfos),sti_compar);
- return sti->abbrev;
-}
-
-
-void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
- int (*needswap)(void *context, const void *a, const void *b),
- void *context) {
- byte *data= array;
- int i, place;
-
- for (i=0; i<nobjs; i++) {
- for (place= i;
- place>0 && needswap(context, data + (place-1)*sz, data + i*sz);
- place--);
- if (place != i) {
- memcpy(tempbuf, data + i*sz, sz);
- memmove(data + (place+1)*sz, data + place*sz, (i-place)*sz);
- memcpy(data + place*sz, tempbuf, sz);
- }
- }
-}
-
-/* SIGPIPE protection. */
-
-void adns__sigpipe_protect(adns_state ads) {
- sigset_t toblock;
- struct sigaction sa;
- int r;
-
- if (ads->iflags & adns_if_nosigpipe) return;
-
- sigfillset(&toblock);
- sigdelset(&toblock,SIGPIPE);
-
- sa.sa_handler= SIG_IGN;
- sigfillset(&sa.sa_mask);
- sa.sa_flags= 0;
-
- r= sigprocmask(SIG_SETMASK,&toblock,&ads->stdsigmask); assert(!r);
- r= sigaction(SIGPIPE,&sa,&ads->stdsigpipe); assert(!r);
-}
-
-void adns__sigpipe_unprotect(adns_state ads) {
- int r;
-
- if (ads->iflags & adns_if_nosigpipe) return;
-
- r= sigaction(SIGPIPE,&ads->stdsigpipe,0); assert(!r);
- r= sigprocmask(SIG_SETMASK,&ads->stdsigmask,0); assert(!r);
-}
diff --git a/adns-0.6/src/internal.h b/adns-0.6/src/internal.h
deleted file mode 100644
index 9e442fe..0000000
--- a/adns-0.6/src/internal.h
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * internal.h
- * - declarations of private objects with external linkage (adns__*)
- * - definitons of internal macros
- * - comments regarding library data structures
- */
-/*
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef ADNS_INTERNAL_H_INCLUDED
-#define ADNS_INTERNAL_H_INCLUDED
-
-#include "config.h"
-typedef unsigned char byte;
-
-#include <stdarg.h>
-#include <assert.h>
-#include <unistd.h>
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
-
-#include <sys/time.h>
-
-#include "adns.h"
-#include "dlist.h"
-
-/* Configuration and constants */
-
-#define MAXSERVERS 5
-#define MAXSORTLIST 15
-#define UDPMAXRETRIES 15
-#define UDPRETRYMS 2000
-#define TCPWAITMS 30000
-#define TCPCONNMS 14000
-#define TCPIDLEMS 30000
-#define MAXTTLBELIEVE (7*86400) /* any TTL > 7 days is capped */
-
-#define DNS_PORT 53
-#define DNS_MAXUDP 512
-#define DNS_MAXDOMAIN 255
-#define DNS_HDRSIZE 12
-#define DNS_IDOFFSET 0
-#define DNS_CLASS_IN 1
-
-#define DNS_INADDR_ARPA "in-addr", "arpa"
-
-#define MAX_POLLFDS ADNS_POLLFDS_RECOMMENDED
-
-typedef enum {
- cc_user,
- cc_entex,
- cc_freq
-} consistency_checks;
-
-typedef enum {
- rcode_noerror,
- rcode_formaterror,
- rcode_servfail,
- rcode_nxdomain,
- rcode_notimp,
- rcode_refused
-} dns_rcode;
-
-/* Shared data structures */
-
-typedef union {
- adns_status status;
- char *cp;
- adns_rrtype type;
- int i;
- struct in_addr ia;
- unsigned long ul;
-} rr_align;
-
-typedef struct {
- int used, avail;
- byte *buf;
-} vbuf;
-
-typedef struct {
- adns_state ads;
- adns_query qu;
- int serv;
- const byte *dgram;
- int dglen, nsstart, nscount, arcount;
- struct timeval now;
-} parseinfo;
-
-typedef struct {
- adns_rrtype type;
- const char *rrtname;
- const char *fmtname;
- int rrsz;
-
- void (*makefinal)(adns_query qu, void *data);
- /* Change memory management of *data.
- * Previously, used alloc_interim, now use alloc_final.
- */
-
- adns_status (*convstring)(vbuf *vb, const void *data);
- /* Converts the RR data to a string representation in vbuf.
- * vbuf will be appended to (it must have been initialised),
- * and will not be null-terminated by convstring.
- */
-
- adns_status (*parse)(const parseinfo *pai, int cbyte, int max, void *store_r);
- /* Parse one RR, in dgram of length dglen, starting at cbyte and
- * extending until at most max.
- *
- * The RR should be stored at *store_r, of length qu->typei->rrsz.
- *
- * If there is an overrun which might indicate truncation, it should set
- * *rdstart to -1; otherwise it may set it to anything else positive.
- *
- * nsstart is the offset of the authority section.
- */
-
- int (*diff_needswap)(adns_state ads, const void *datap_a, const void *datap_b);
- /* Returns !0 if RR a should be strictly after RR b in the sort order,
- * 0 otherwise. Must not fail.
- */
-} typeinfo;
-
-typedef struct allocnode {
- struct allocnode *next, *back;
-} allocnode;
-
-union maxalign {
- byte d[1];
- struct in_addr ia;
- long l;
- void *p;
- void (*fp)(void);
- union maxalign *up;
-} data;
-
-typedef struct {
- void *ext;
- void (*callback)(adns_query parent, adns_query child);
- union {
- adns_rr_addr ptr_parent_addr;
- adns_rr_hostaddr *hostaddr;
- } info;
-} qcontext;
-
-struct adns__query {
- adns_state ads;
- enum { query_tosend, query_tcpw, query_childw, query_done } state;
- adns_query back, next, parent;
- struct { adns_query head, tail; } children;
- struct { adns_query back, next; } siblings;
- struct { allocnode *head, *tail; } allocations;
- int interim_allocd, preserved_allocd;
- void *final_allocspace;
-
- const typeinfo *typei;
- byte *query_dgram;
- int query_dglen;
-
- vbuf vb;
- /* General-purpose messing-about buffer.
- * Wherever a `big' interface is crossed, this may be corrupted/changed
- * unless otherwise specified.
- */
-
- adns_answer *answer;
- /* This is allocated when a query is submitted, to avoid being unable
- * to relate errors to queries if we run out of memory. During
- * query processing status, rrs is 0. cname is set if
- * we found a cname (this corresponds to cname_dgram in the query
- * structure). type is set from the word go. nrrs and rrs
- * are set together, when we find how many rrs there are.
- * owner is set during querying unless we're doing searchlist,
- * in which case it is set only when we find an answer.
- */
-
- byte *cname_dgram;
- int cname_dglen, cname_begin;
- /* If non-0, has been allocated using . */
-
- vbuf search_vb;
- int search_origlen, search_pos, search_doneabs;
- /* Used by the searching algorithm. The query domain in textual form
- * is copied into the vbuf, and _origlen set to its length. Then
- * we walk the searchlist, if we want to. _pos says where we are
- * (next entry to try), and _doneabs says whether we've done the
- * absolute query yet (0=not yet, 1=done, -1=must do straight away,
- * but not done yet). If flags doesn't have adns_qf_search then
- * the vbuf is initialised but empty and everything else is zero.
- */
-
- int id, flags, retries;
- int udpnextserver;
- unsigned long udpsent; /* bitmap indexed by server */
- struct timeval timeout;
- time_t expires; /* Earliest expiry time of any record we used. */
-
- qcontext ctx;
-
- /* Possible states:
- *
- * state Queue child id nextudpserver udpsent tcpfailed
- *
- * tosend NONE null >=0 0 zero zero
- * tosend udpw null >=0 any nonzero zero
- * tosend NONE null >=0 any nonzero zero
- *
- * tcpw tcpw null >=0 irrelevant any any
- *
- * child childw set >=0 irrelevant irrelevant irrelevant
- * child NONE null >=0 irrelevant irrelevant irrelevant
- * done output null -1 irrelevant irrelevant irrelevant
- *
- * Queries are only not on a queue when they are actually being processed.
- * Queries in state tcpw/tcpw have been sent (or are in the to-send buffer)
- * iff the tcp connection is in state server_ok.
- *
- * +------------------------+
- * START -----> | tosend/NONE |
- * +------------------------+
- * / |\ \
- * too big for UDP / UDP timeout \ \ send via UDP
- * send via TCP / more retries \ \
- * when conn'd / desired \ \
- * | | |
- * v | v
- * +-----------+ +-------------+
- * | tcpw/tcpw | ________ | tosend/udpw |
- * +-----------+ \ +-------------+
- * | | | UDP timeout | |
- * | | | no more | |
- * | | | retries | |
- * \ | TCP died | desired | |
- * \ \ no more | | |
- * \ \ servers | TCP / |
- * \ \ to try | timeout / |
- * got \ \ v |_ | got
- * reply \ _| +------------------+ / reply
- * \ | done/output FAIL | /
- * \ +------------------+ /
- * \ /
- * _| |_
- * (..... got reply ....)
- * / \
- * need child query/ies / \ no child query
- * / \
- * |_ _|
- * +---------------+ +----------------+
- * | childw/childw | ----------------> | done/output OK |
- * +---------------+ children done +----------------+
- */
-};
-
-struct query_queue { adns_query head, tail; };
-
-struct adns__state {
- adns_initflags iflags;
- FILE *diagfile;
- int configerrno;
- struct query_queue udpw, tcpw, childw, output;
- adns_query forallnext;
- int nextid, udpsocket, tcpsocket;
- vbuf tcpsend, tcprecv;
- int nservers, nsortlist, nsearchlist, searchndots, tcpserver, tcprecv_skip;
- enum adns__tcpstate {
- server_disconnected, server_connecting,
- server_ok, server_broken
- } tcpstate;
- struct timeval tcptimeout;
- /* This will have tv_sec==0 if it is not valid.
- * It will always be valid if tcpstate _connecting.
- * When _ok, it will be nonzero if we are idle
- * (ie, tcpw queue is empty) and counting down.
- */
- struct sigaction stdsigpipe;
- sigset_t stdsigmask;
- struct pollfd pollfds_buf[MAX_POLLFDS];
- struct server {
- struct in_addr addr;
- } servers[MAXSERVERS];
- struct sortlist {
- struct in_addr base, mask;
- } sortlist[MAXSORTLIST];
- char **searchlist;
-};
-
-/* From setup.c: */
-
-int adns__setnonblock(adns_state ads, int fd); /* => errno value */
-
-/* From general.c: */
-
-void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
- int serv, adns_query qu, const char *fmt, va_list al);
-
-void adns__debug(adns_state ads, int serv, adns_query qu,
- const char *fmt, ...) PRINTFFORMAT(4,5);
-void adns__warn(adns_state ads, int serv, adns_query qu,
- const char *fmt, ...) PRINTFFORMAT(4,5);
-void adns__diag(adns_state ads, int serv, adns_query qu,
- const char *fmt, ...) PRINTFFORMAT(4,5);
-
-int adns__vbuf_ensure(vbuf *vb, int want);
-int adns__vbuf_appendstr(vbuf *vb, const char *data); /* does not include nul */
-int adns__vbuf_append(vbuf *vb, const byte *data, int len);
-/* 1=>success, 0=>realloc failed */
-void adns__vbuf_appendq(vbuf *vb, const byte *data, int len);
-void adns__vbuf_init(vbuf *vb);
-void adns__vbuf_free(vbuf *vb);
-
-const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
- vbuf *vb, const byte *dgram, int dglen, int cbyte);
-/* Unpicks a domain in a datagram and returns a string suitable for
- * printing it as. Never fails - if an error occurs, it will
- * return some kind of string describing the error.
- *
- * serv may be -1 and qu may be 0. vb must have been initialised,
- * and will be left in an arbitrary consistent state.
- *
- * Returns either vb->buf, or a pointer to a string literal. Do not modify
- * vb before using the return value.
- */
-
-void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
- int (*needswap)(void *context, const void *a, const void *b),
- void *context);
-/* Does an insertion sort of array which must contain nobjs objects
- * each sz bytes long. tempbuf must point to a buffer at least
- * sz bytes long. needswap should return !0 if a>b (strictly, ie
- * wrong order) 0 if a<=b (ie, order is fine).
- */
-
-void adns__sigpipe_protect(adns_state);
-void adns__sigpipe_unprotect(adns_state);
-/* If SIGPIPE protection is not disabled, will block all signals except
- * SIGPIPE, and set SIGPIPE's disposition to SIG_IGN. (And then restore.)
- * Each call to _protect must be followed by a call to _unprotect before
- * any significant amount of code gets to run, since the old signal mask
- * is stored in the adns structure.
- */
-
-/* From transmit.c: */
-
-adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r,
- const char *owner, int ol,
- const typeinfo *typei, adns_queryflags flags);
-/* Assembles a query packet in vb. A new id is allocated and returned.
- */
-
-adns_status adns__mkquery_frdgram(adns_state ads, vbuf *vb, int *id_r,
- const byte *qd_dgram, int qd_dglen, int qd_begin,
- adns_rrtype type, adns_queryflags flags);
-/* Same as adns__mkquery, but takes the owner domain from an existing datagram.
- * That domain must be correct and untruncated.
- */
-
-void adns__querysend_tcp(adns_query qu, struct timeval now);
-/* Query must be in state tcpw/tcpw; it will be sent if possible and
- * no further processing can be done on it for now. The connection
- * might be broken, but no reconnect will be attempted.
- */
-
-void adns__query_send(adns_query qu, struct timeval now);
-/* Query must be in state tosend/NONE; it will be moved to a new state,
- * and no further processing can be done on it for now.
- * (Resulting state is one of udp/timew, tcpwait/timew (if server not connected),
- * tcpsent/timew, child/childw or done/output.)
- * __query_send may decide to use either UDP or TCP depending whether
- * _qf_usevc is set (or has become set) and whether the query is too
- * large.
- */
-
-/* From query.c: */
-
-adns_status adns__internal_submit(adns_state ads, adns_query *query_r,
- const typeinfo *typei, vbuf *qumsg_vb, int id,
- adns_queryflags flags, struct timeval now,
- const qcontext *ctx);
-/* Submits a query (for internal use, called during external submits).
- *
- * The new query is returned in *query_r, or we return adns_s_nomemory.
- *
- * The query datagram should already have been assembled in qumsg_vb;
- * the memory for it is _taken over_ by this routine whether it
- * succeeds or fails (if it succeeds, the vbuf is reused for qu->vb).
- *
- * *ctx is copied byte-for-byte into the query.
- *
- * When the child query is done, ctx->callback will be called. The
- * child will already have been taken off both the global list of
- * queries in ads and the list of children in the parent. The child
- * will be freed when the callback returns. The parent will have been
- * taken off the global childw queue.
- *
- * The callback should either call adns__query_done, if it is
- * complete, or adns__query_fail, if an error has occurred, in which
- * case the other children (if any) will be cancelled. If the parent
- * has more unfinished children (or has just submitted more) then the
- * callback may choose to wait for them - it must then put the parent
- * back on the childw queue.
- */
-
-void adns__search_next(adns_state ads, adns_query qu, struct timeval now);
-/* Walks down the searchlist for a query with adns_qf_search.
- * The query should have just had a negative response, or not had
- * any queries sent yet, and should not be on any queue.
- * The query_dgram if any will be freed and forgotten and a new
- * one constructed from the search_* members of the query.
- *
- * Cannot fail (in case of error, calls adns__query_fail).
- */
-
-void *adns__alloc_interim(adns_query qu, size_t sz);
-void *adns__alloc_preserved(adns_query qu, size_t sz);
-/* Allocates some memory, and records which query it came from
- * and how much there was.
- *
- * If an error occurs in the query, all the memory from _interim is
- * simply freed. If the query succeeds, one large buffer will be made
- * which is big enough for all these allocations, and then
- * adns__alloc_final will get memory from this buffer.
- *
- * _alloc_interim can fail (and return 0).
- * The caller must ensure that the query is failed.
- *
- * The memory from _preserved is is kept and transferred into the
- * larger buffer - unless we run out of memory, in which case it too
- * is freed. When you use _preserved you have to add code to the
- * x_nomem error exit case in adns__makefinal_query to clear out the
- * pointers you made to those allocations, because that's when they're
- * thrown away; you should also make a note in the declaration of
- * those pointer variables, to note that they are _preserved rather
- * than _interim. If they're in the answer, note it here:
- * answer->cname and answer->owner are _preserved.
- */
-
-void adns__transfer_interim(adns_query from, adns_query to, void *block, size_t sz);
-/* Transfers an interim allocation from one query to another, so that
- * the `to' query will have room for the data when we get to makefinal
- * and so that the free will happen when the `to' query is freed
- * rather than the `from' query.
- *
- * It is legal to call adns__transfer_interim with a null pointer; this
- * has no effect.
- *
- * _transfer_interim also ensures that the expiry time of the `to' query
- * is no later than that of the `from' query, so that child queries'
- * TTLs get inherited by their parents.
- */
-
-void *adns__alloc_mine(adns_query qu, size_t sz);
-/* Like _interim, but does not record the length for later
- * copying into the answer. This just ensures that the memory
- * will be freed when we're done with the query.
- */
-
-void *adns__alloc_final(adns_query qu, size_t sz);
-/* Cannot fail, and cannot return 0.
- */
-
-void adns__makefinal_block(adns_query qu, void **blpp, size_t sz);
-void adns__makefinal_str(adns_query qu, char **strp);
-
-void adns__reset_preserved(adns_query qu);
-/* Resets all of the memory management stuff etc. to take account of
- * only the _preserved stuff from _alloc_preserved. Used when we find
- * an error somewhere and want to just report the error (with perhaps
- * CNAME, owner, etc. info), and also when we're halfway through RRs
- * in a datagram and discover that we need to retry the query.
- */
-
-void adns__query_done(adns_query qu);
-void adns__query_fail(adns_query qu, adns_status stat);
-
-/* From reply.c: */
-
-void adns__procdgram(adns_state ads, const byte *dgram, int len,
- int serv, int viatcp, struct timeval now);
-/* This function is allowed to cause new datagrams to be constructed
- * and sent, or even new queries to be started. However,
- * query-sending functions are not allowed to call any general event
- * loop functions in case they accidentally call this.
- *
- * Ie, receiving functions may call sending functions.
- * Sending functions may NOT call receiving functions.
- */
-
-/* From types.c: */
-
-const typeinfo *adns__findtype(adns_rrtype type);
-
-/* From parse.c: */
-
-typedef struct {
- adns_state ads;
- adns_query qu;
- int serv;
- const byte *dgram;
- int dglen, max, cbyte, namelen;
- int *dmend_r;
-} findlabel_state;
-
-void adns__findlabel_start(findlabel_state *fls, adns_state ads,
- int serv, adns_query qu,
- const byte *dgram, int dglen, int max,
- int dmbegin, int *dmend_rlater);
-/* Finds labels in a domain in a datagram.
- *
- * Call this routine first.
- * dmend_rlater may be null. ads (and of course fls) may not be.
- * serv may be -1, qu may be null - they are for error reporting.
- */
-
-adns_status adns__findlabel_next(findlabel_state *fls, int *lablen_r, int *labstart_r);
-/* Then, call this one repeatedly.
- *
- * It will return adns_s_ok if all is well, and tell you the length
- * and start of successive labels. labstart_r may be null, but
- * lablen_r must not be.
- *
- * After the last label, it will return with *lablen_r zero.
- * Do not then call it again; instead, just throw away the findlabel_state.
- *
- * *dmend_rlater will have been set to point to the next part of
- * the datagram after the label (or after the uncompressed part,
- * if compression was used). *namelen_rlater will have been set
- * to the length of the domain name (total length of labels plus
- * 1 for each intervening dot).
- *
- * If the datagram appears to be truncated, *lablen_r will be -1.
- * *dmend_rlater, *labstart_r and *namelen_r may contain garbage.
- * Do not call _next again.
- *
- * There may also be errors, in which case *dmend_rlater,
- * *namelen_rlater, *lablen_r and *labstart_r may contain garbage.
- * Do not then call findlabel_next again.
- */
-
-typedef enum {
- pdf_quoteok= 0x001
-} parsedomain_flags;
-
-adns_status adns__parse_domain(adns_state ads, int serv, adns_query qu,
- vbuf *vb, parsedomain_flags flags,
- const byte *dgram, int dglen, int *cbyte_io, int max);
-/* vb must already have been initialised; it will be reset if necessary.
- * If there is truncation, vb->used will be set to 0; otherwise
- * (if there is no error) vb will be null-terminated.
- * If there is an error vb and *cbyte_io may be left indeterminate.
- *
- * serv may be -1 and qu may be 0 - they are used for error reporting only.
- */
-
-adns_status adns__parse_domain_more(findlabel_state *fls, adns_state ads,
- adns_query qu, vbuf *vb, parsedomain_flags flags,
- const byte *dgram);
-/* Like adns__parse_domain, but you pass it a pre-initialised findlabel_state,
- * for continuing an existing domain or some such of some kind. Also, unlike
- * _parse_domain, the domain data will be appended to vb, rather than replacing
- * the existing contents.
- */
-
-adns_status adns__findrr(adns_query qu, int serv,
- const byte *dgram, int dglen, int *cbyte_io,
- int *type_r, int *class_r, unsigned long *ttl_r,
- int *rdlen_r, int *rdstart_r,
- int *ownermatchedquery_r);
-/* Finds the extent and some of the contents of an RR in a datagram
- * and does some checks. The datagram is *dgram, length dglen, and
- * the RR starts at *cbyte_io (which is updated afterwards to point
- * to the end of the RR).
- *
- * The type, class, TTL and RRdata length and start are returned iff
- * the corresponding pointer variables are not null. type_r, class_r
- * and ttl_r may not be null. The TTL will be capped.
- *
- * If ownermatchedquery_r != 0 then the owner domain of this
- * RR will be compared with that in the query (or, if the query
- * has gone to a CNAME lookup, with the canonical name).
- * In this case, *ownermatchedquery_r will be set to 0 or 1.
- * The query datagram (or CNAME datagram) MUST be valid and not truncated.
- *
- * If there is truncation then *type_r will be set to -1 and
- * *cbyte_io, *class_r, *rdlen_r, *rdstart_r and *eo_matched_r will be
- * undefined.
- *
- * qu must obviously be non-null.
- *
- * If an error is returned then *type_r will be undefined too.
- */
-
-adns_status adns__findrr_anychk(adns_query qu, int serv,
- const byte *dgram, int dglen, int *cbyte_io,
- int *type_r, int *class_r, unsigned long *ttl_r,
- int *rdlen_r, int *rdstart_r,
- const byte *eo_dgram, int eo_dglen, int eo_cbyte,
- int *eo_matched_r);
-/* Like adns__findrr_checked, except that the datagram and
- * owner to compare with can be specified explicitly.
- *
- * If the caller thinks they know what the owner of the RR ought to
- * be they can pass in details in eo_*: this is another (or perhaps
- * the same datagram), and a pointer to where the putative owner
- * starts in that datagram. In this case *eo_matched_r will be set
- * to 1 if the datagram matched or 0 if it did not. Either
- * both eo_dgram and eo_matched_r must both be non-null, or they
- * must both be null (in which case eo_dglen and eo_cbyte will be ignored).
- * The eo datagram and contained owner domain MUST be valid and
- * untruncated.
- */
-
-void adns__update_expires(adns_query qu, unsigned long ttl, struct timeval now);
-/* Updates the `expires' field in the query, so that it doesn't exceed
- * now + ttl.
- */
-
-int vbuf__append_quoted1035(vbuf *vb, const byte *buf, int len);
-
-/* From event.c: */
-
-void adns__tcp_broken(adns_state ads, const char *what, const char *why);
-/* what and why may be both 0, or both non-0. */
-
-void adns__tcp_tryconnect(adns_state ads, struct timeval now);
-
-void adns__autosys(adns_state ads, struct timeval now);
-/* Make all the system calls we want to if the application wants us to.
- * Must not be called from within adns internal processing functions,
- * lest we end up in recursive descent !
- */
-
-void adns__must_gettimeofday(adns_state ads, const struct timeval **now_io,
- struct timeval *tv_buf);
-
-int adns__pollfds(adns_state ads, struct pollfd pollfds_buf[MAX_POLLFDS]);
-void adns__fdevents(adns_state ads,
- const struct pollfd *pollfds, int npollfds,
- int maxfd, const fd_set *readfds,
- const fd_set *writefds, const fd_set *exceptfds,
- struct timeval now, int *r_r);
-int adns__internal_check(adns_state ads,
- adns_query *query_io,
- adns_answer **answer,
- void **context_r);
-
-void adns__timeouts(adns_state ads, int act,
- struct timeval **tv_io, struct timeval *tvbuf,
- struct timeval now);
-/* If act is !0, then this will also deal with the TCP connection
- * if previous events broke it or require it to be connected.
- */
-
-/* From check.c: */
-
-void adns__consistency(adns_state ads, adns_query qu, consistency_checks cc);
-
-/* Useful static inline functions: */
-
-static inline int ctype_whitespace(int c) { return c==' ' || c=='\n' || c=='\t'; }
-static inline int ctype_digit(int c) { return c>='0' && c<='9'; }
-static inline int ctype_alpha(int c) {
- return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
-}
-static inline int ctype_822special(int c) { return strchr("()<>@,;:\\\".[]",c) != 0; }
-
-static inline int errno_resources(int e) { return e==ENOMEM || e==ENOBUFS; }
-
-/* Useful macros */
-
-#define MEM_ROUND(sz) \
- (( ((sz)+sizeof(union maxalign)-1) / sizeof(union maxalign) ) \
- * sizeof(union maxalign) )
-
-#define GETIL_B(cb) (((dgram)[(cb)++]) & 0x0ff)
-#define GET_B(cb,tv) ((tv)= GETIL_B((cb)))
-#define GET_W(cb,tv) ((tv)=0, (tv)|=(GETIL_B((cb))<<8), (tv)|=GETIL_B(cb), (tv))
-#define GET_L(cb,tv) ( (tv)=0, \
- (tv)|=(GETIL_B((cb))<<24), \
- (tv)|=(GETIL_B((cb))<<16), \
- (tv)|=(GETIL_B((cb))<<8), \
- (tv)|=GETIL_B(cb), \
- (tv) )
-
-#endif
diff --git a/adns-0.6/src/parse.c b/adns-0.6/src/parse.c
deleted file mode 100644
index 9a4e0c7..0000000
--- a/adns-0.6/src/parse.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * parse.c
- * - parsing assistance functions (mainly for domains inside datagrams)
- */
-/*
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "internal.h"
-
-int vbuf__append_quoted1035(vbuf *vb, const byte *buf, int len) {
- char qbuf[10];
- int i, ch;
-
- while (len) {
- qbuf[0]= 0;
- for (i=0; i<len; i++) {
- ch= buf[i];
- if (ch == '.' || ch == '"' || ch == '(' || ch == ')' ||
- ch == '@' || ch == ';' || ch == '$' || ch == '\\') {
- sprintf(qbuf,"\\%c",ch);
- break;
- } else if (ch <= ' ' || ch >= 127) {
- sprintf(qbuf,"\\%03o",ch);
- break;
- }
- }
- if (!adns__vbuf_append(vb,buf,i) || !adns__vbuf_append(vb,qbuf,strlen(qbuf)))
- return 0;
- if (i<len) i++;
- buf+= i;
- len-= i;
- }
- return 1;
-}
-
-void adns__findlabel_start(findlabel_state *fls, adns_state ads,
- int serv, adns_query qu,
- const byte *dgram, int dglen, int max,
- int dmbegin, int *dmend_rlater) {
- fls->ads= ads;
- fls->qu= qu;
- fls->serv= serv;
- fls->dgram= dgram;
- fls->dglen= dglen;
- fls->max= max;
- fls->cbyte= dmbegin;
- fls->namelen= 0;
- fls->dmend_r= dmend_rlater;
-}
-
-adns_status adns__findlabel_next(findlabel_state *fls,
- int *lablen_r, int *labstart_r) {
- int lablen, jumped, jumpto;
- const char *dgram;
-
- jumped= 0;
- dgram= fls->dgram;
- for (;;) {
- if (fls->cbyte >= fls->dglen) goto x_truncated;
- if (fls->cbyte >= fls->max) goto x_badresponse;
- GET_B(fls->cbyte,lablen);
- if (!(lablen & 0x0c0)) break;
- if ((lablen & 0x0c0) != 0x0c0) return adns_s_unknownformat;
- if (jumped++) {
- adns__diag(fls->ads,fls->serv,fls->qu,"compressed datagram contains loop");
- return adns_s_invalidresponse;
- }
- if (fls->cbyte >= fls->dglen) goto x_truncated;
- if (fls->cbyte >= fls->max) goto x_badresponse;
- GET_B(fls->cbyte,jumpto);
- jumpto |= (lablen&0x3f)<<8;
- if (fls->dmend_r) *(fls->dmend_r)= fls->cbyte;
- fls->cbyte= jumpto;
- fls->dmend_r= 0; fls->max= fls->dglen+1;
- }
- if (labstart_r) *labstart_r= fls->cbyte;
- if (lablen) {
- if (fls->namelen) fls->namelen++;
- fls->namelen+= lablen;
- if (fls->namelen > DNS_MAXDOMAIN) return adns_s_answerdomaintoolong;
- fls->cbyte+= lablen;
- if (fls->cbyte > fls->dglen) goto x_truncated;
- if (fls->cbyte > fls->max) goto x_badresponse;
- } else {
- if (fls->dmend_r) *(fls->dmend_r)= fls->cbyte;
- }
- *lablen_r= lablen;
-/*if (labstart_r) fprintf(stderr,"label %d >%.*s<\n",lablen,lablen,fls->dgram+*labstart_r);*/
- return adns_s_ok;
-
- x_truncated:
- *lablen_r= -1;
- return adns_s_ok;
-
- x_badresponse:
- adns__diag(fls->ads,fls->serv,fls->qu,"label in domain runs beyond end of domain");
- return adns_s_invalidresponse;
-}
-
-adns_status adns__parse_domain(adns_state ads, int serv, adns_query qu,
- vbuf *vb, adns_queryflags flags,
- const byte *dgram, int dglen, int *cbyte_io, int max) {
- findlabel_state fls;
-
- adns__findlabel_start(&fls,ads, serv,qu, dgram,dglen,max, *cbyte_io,cbyte_io);
- vb->used= 0;
- return adns__parse_domain_more(&fls,ads,qu, vb,flags,dgram);
-}
-
-adns_status adns__parse_domain_more(findlabel_state *fls, adns_state ads,
- adns_query qu, vbuf *vb, parsedomain_flags flags,
- const byte *dgram) {
- int lablen, labstart, i, ch, first;
- adns_status st;
-
- first= 1;
- for (;;) {
- st= adns__findlabel_next(fls,&lablen,&labstart);
- if (st) return st;
- if (lablen<0) { vb->used=0; return adns_s_ok; }
- if (!lablen) break;
- if (first) {
- first= 0;
- } else {
- if (!adns__vbuf_append(vb,".",1)) return adns_s_nomemory;
- }
- if (flags & pdf_quoteok) {
- if (!vbuf__append_quoted1035(vb,dgram+labstart,lablen))
- return adns_s_nomemory;
- } else {
- ch= dgram[labstart];
- if (!ctype_alpha(ch) && !ctype_digit(ch)) return adns_s_answerdomaininvalid;
- for (i= labstart+1; i<labstart+lablen; i++) {
- ch= dgram[i];
- if (ch != '-' && !ctype_alpha(ch) && !ctype_digit(ch))
- return adns_s_answerdomaininvalid;
- }
- if (!adns__vbuf_append(vb,dgram+labstart,lablen))
- return adns_s_nomemory;
- }
- }
- if (!adns__vbuf_append(vb,"",1)) return adns_s_nomemory;
- return adns_s_ok;
-}
-
-adns_status adns__findrr_anychk(adns_query qu, int serv,
- const byte *dgram, int dglen, int *cbyte_io,
- int *type_r, int *class_r, unsigned long *ttl_r,
- int *rdlen_r, int *rdstart_r,
- const byte *eo_dgram, int eo_dglen, int eo_cbyte,
- int *eo_matched_r) {
- findlabel_state fls, eo_fls;
- int cbyte;
-
- int tmp, rdlen, mismatch;
- unsigned long ttl;
- int lablen, labstart, ch;
- int eo_lablen, eo_labstart, eo_ch;
- adns_status st;
-
- cbyte= *cbyte_io;
-
- adns__findlabel_start(&fls,qu->ads, serv,qu, dgram,dglen,dglen,cbyte,&cbyte);
- if (eo_dgram) {
- adns__findlabel_start(&eo_fls,qu->ads, -1,0, eo_dgram,eo_dglen,eo_dglen,eo_cbyte,0);
- mismatch= 0;
- } else {
- mismatch= 1;
- }
-
- for (;;) {
- st= adns__findlabel_next(&fls,&lablen,&labstart);
- if (st) return st;
- if (lablen<0) goto x_truncated;
-
- if (!mismatch) {
- st= adns__findlabel_next(&eo_fls,&eo_lablen,&eo_labstart);
- assert(!st); assert(eo_lablen>=0);
- if (lablen != eo_lablen) mismatch= 1;
- while (!mismatch && eo_lablen-- > 0) {
- ch= dgram[labstart++]; if (ctype_alpha(ch)) ch &= ~32;
- eo_ch= eo_dgram[eo_labstart++]; if (ctype_alpha(eo_ch)) eo_ch &= ~32;
- if (ch != eo_ch) mismatch= 1;
- }
- }
- if (!lablen) break;
- }
- if (eo_matched_r) *eo_matched_r= !mismatch;
-
- if (cbyte+10>dglen) goto x_truncated;
- GET_W(cbyte,tmp); *type_r= tmp;
- GET_W(cbyte,tmp); *class_r= tmp;
-
- GET_L(cbyte,ttl);
- if (ttl > MAXTTLBELIEVE) ttl= MAXTTLBELIEVE;
- *ttl_r= ttl;
-
- GET_W(cbyte,rdlen); if (rdlen_r) *rdlen_r= rdlen;
- if (rdstart_r) *rdstart_r= cbyte;
- cbyte+= rdlen;
- if (cbyte>dglen) goto x_truncated;
- *cbyte_io= cbyte;
- return adns_s_ok;
-
- x_truncated:
- *type_r= -1;
- return 0;
-}
-
-adns_status adns__findrr(adns_query qu, int serv,
- const byte *dgram, int dglen, int *cbyte_io,
- int *type_r, int *class_r, unsigned long *ttl_r,
- int *rdlen_r, int *rdstart_r,
- int *ownermatchedquery_r) {
- if (!ownermatchedquery_r) {
- return adns__findrr_anychk(qu,serv,
- dgram,dglen,cbyte_io,
- type_r,class_r,ttl_r,rdlen_r,rdstart_r,
- 0,0,0, 0);
- } else if (!qu->cname_dgram) {
- return adns__findrr_anychk(qu,serv,
- dgram,dglen,cbyte_io,
- type_r,class_r,ttl_r,rdlen_r,rdstart_r,
- qu->query_dgram,qu->query_dglen,DNS_HDRSIZE,
- ownermatchedquery_r);
- } else {
- return adns__findrr_anychk(qu,serv,
- dgram,dglen,cbyte_io,
- type_r,class_r,ttl_r,rdlen_r,rdstart_r,
- qu->cname_dgram,qu->cname_dglen,qu->cname_begin,
- ownermatchedquery_r);
- }
-}
diff --git a/adns-0.6/src/poll.c b/adns-0.6/src/poll.c
deleted file mode 100644
index 45dc437..0000000
--- a/adns-0.6/src/poll.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * poll.c
- * - wrappers for poll(2)
- */
-/*
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <limits.h>
-#include <string.h>
-
-#include "internal.h"
-
-#ifdef HAVE_POLL
-
-int adns_beforepoll(adns_state ads, struct pollfd *fds, int *nfds_io, int *timeout_io,
- const struct timeval *now) {
- struct timeval tv_nowbuf, tv_tobuf, *tv_to;
- int space, found, timeout_ms, r;
- struct pollfd fds_tmp[MAX_POLLFDS];
-
- adns__consistency(ads,0,cc_entex);
-
- if (timeout_io) {
- adns__must_gettimeofday(ads,&now,&tv_nowbuf);
- if (!now) { *nfds_io= 0; r= 0; goto xit; }
-
- timeout_ms= *timeout_io;
- if (timeout_ms == -1) {
- tv_to= 0;
- } else {
- tv_tobuf.tv_sec= timeout_ms / 1000;
- tv_tobuf.tv_usec= (timeout_ms % 1000)*1000;
- tv_to= &tv_tobuf;
- }
-
- adns__timeouts(ads, 0, &tv_to,&tv_tobuf, *now);
-
- if (tv_to) {
- assert(tv_to == &tv_tobuf);
- timeout_ms= (tv_tobuf.tv_usec+999)/1000;
- assert(tv_tobuf.tv_sec < (INT_MAX-timeout_ms)/1000);
- timeout_ms += tv_tobuf.tv_sec*1000;
- } else {
- timeout_ms= -1;
- }
- *timeout_io= timeout_ms;
- }
-
- space= *nfds_io;
- if (space >= MAX_POLLFDS) {
- found= adns__pollfds(ads,fds);
- *nfds_io= found;
- } else {
- found= adns__pollfds(ads,fds_tmp);
- *nfds_io= found;
- if (space < found) { r= ERANGE; goto xit; }
- memcpy(fds,fds_tmp,sizeof(struct pollfd)*found);
- }
- r= 0;
-xit:
- adns__consistency(ads,0,cc_entex);
- return r;
-}
-
-void adns_afterpoll(adns_state ads, const struct pollfd *fds, int nfds,
- const struct timeval *now) {
- struct timeval tv_buf;
-
- adns__consistency(ads,0,cc_entex);
- adns__must_gettimeofday(ads,&now,&tv_buf);
- if (now) {
- adns__timeouts(ads, 1, 0,0, *now);
- adns__fdevents(ads, fds,nfds, 0,0,0,0, *now,0);
- }
- adns__consistency(ads,0,cc_entex);
-}
-
-int adns_wait_poll(adns_state ads,
- adns_query *query_io,
- adns_answer **answer_r,
- void **context_r) {
- int r, nfds, to;
- struct pollfd fds[MAX_POLLFDS];
-
- adns__consistency(ads,0,cc_entex);
-
- for (;;) {
- r= adns__internal_check(ads,query_io,answer_r,context_r);
- if (r != EAGAIN) goto xit;
- nfds= MAX_POLLFDS; to= -1;
- adns_beforepoll(ads,fds,&nfds,&to,0);
- r= poll(fds,nfds,to);
- if (r == -1) {
- if (errno == EINTR) {
- if (ads->iflags & adns_if_eintr) { r= EINTR; goto xit; }
- } else {
- adns__diag(ads,-1,0,"poll failed in wait: %s",strerror(errno));
- adns_globalsystemfailure(ads);
- }
- } else {
- assert(r >= 0);
- adns_afterpoll(ads,fds,nfds,0);
- }
- }
-
- xit:
- adns__consistency(ads,0,cc_entex);
- return r;
-}
-
-#endif
diff --git a/adns-0.6/src/query.c b/adns-0.6/src/query.c
deleted file mode 100644
index 37306d1..0000000
--- a/adns-0.6/src/query.c
+++ /dev/null
@@ -1,540 +0,0 @@
-/*
- * query.c
- * - overall query management (allocation, completion)
- * - per-query memory management
- * - query submission and cancellation (user-visible and internal)
- */
-/*
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "internal.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <sys/time.h>
-
-#include "internal.h"
-
-static adns_query query_alloc(adns_state ads, const typeinfo *typei,
- adns_queryflags flags, struct timeval now) {
- /* Allocate a virgin query and return it. */
- adns_query qu;
-
- qu= malloc(sizeof(*qu)); if (!qu) return 0;
- qu->answer= malloc(sizeof(*qu->answer)); if (!qu->answer) { free(qu); return 0; }
-
- qu->ads= ads;
- qu->state= query_tosend;
- qu->back= qu->next= qu->parent= 0;
- LIST_INIT(qu->children);
- LINK_INIT(qu->siblings);
- LIST_INIT(qu->allocations);
- qu->interim_allocd= 0;
- qu->preserved_allocd= 0;
- qu->final_allocspace= 0;
-
- qu->typei= typei;
- qu->query_dgram= 0;
- qu->query_dglen= 0;
- adns__vbuf_init(&qu->vb);
-
- qu->cname_dgram= 0;
- qu->cname_dglen= qu->cname_begin= 0;
-
- adns__vbuf_init(&qu->search_vb);
- qu->search_origlen= qu->search_pos= qu->search_doneabs= 0;
-
- qu->id= 0;
- qu->flags= flags;
- qu->retries= 0;
- qu->udpnextserver= 0;
- qu->udpsent= 0;
- timerclear(&qu->timeout);
- qu->expires= now.tv_sec + MAXTTLBELIEVE;
-
- memset(&qu->ctx,0,sizeof(qu->ctx));
-
- qu->answer->status= adns_s_ok;
- qu->answer->cname= qu->answer->owner= 0;
- qu->answer->type= typei->type;
- qu->answer->expires= -1;
- qu->answer->nrrs= 0;
- qu->answer->rrs.untyped= 0;
- qu->answer->rrsz= typei->rrsz;
-
- return qu;
-}
-
-static void query_submit(adns_state ads, adns_query qu,
- const typeinfo *typei, vbuf *qumsg_vb, int id,
- adns_queryflags flags, struct timeval now) {
- /* Fills in the query message in for a previously-allocated query,
- * and submits it. Cannot fail. Takes over the memory for qumsg_vb.
- */
-
- qu->vb= *qumsg_vb;
- adns__vbuf_init(qumsg_vb);
-
- qu->query_dgram= malloc(qu->vb.used);
- if (!qu->query_dgram) { adns__query_fail(qu,adns_s_nomemory); return; }
-
- qu->id= id;
- qu->query_dglen= qu->vb.used;
- memcpy(qu->query_dgram,qu->vb.buf,qu->vb.used);
-
- adns__query_send(qu,now);
-}
-
-adns_status adns__internal_submit(adns_state ads, adns_query *query_r,
- const typeinfo *typei, vbuf *qumsg_vb, int id,
- adns_queryflags flags, struct timeval now,
- const qcontext *ctx) {
- adns_query qu;
-
- qu= query_alloc(ads,typei,flags,now);
- if (!qu) { adns__vbuf_free(qumsg_vb); return adns_s_nomemory; }
- *query_r= qu;
-
- memcpy(&qu->ctx,ctx,sizeof(qu->ctx));
- query_submit(ads,qu, typei,qumsg_vb,id,flags,now);
-
- return adns_s_ok;
-}
-
-static void query_simple(adns_state ads, adns_query qu,
- const char *owner, int ol,
- const typeinfo *typei, adns_queryflags flags,
- struct timeval now) {
- vbuf vb;
- int id;
- adns_status stat;
-
- vb= qu->vb;
-
- stat= adns__mkquery(ads,&vb,&id, owner,ol, typei,flags);
- if (stat) { adns__query_fail(qu,stat); return; }
-
- query_submit(ads,qu, typei,&vb,id, flags,now);
-}
-
-void adns__search_next(adns_state ads, adns_query qu, struct timeval now) {
- const char *nextentry;
- adns_status stat;
-
- if (qu->search_doneabs<0) {
- nextentry= 0;
- qu->search_doneabs= 1;
- } else {
- if (qu->search_pos >= ads->nsearchlist) {
- if (qu->search_doneabs) {
- stat= adns_s_nxdomain; goto x_fail;
- return;
- } else {
- nextentry= 0;
- qu->search_doneabs= 1;
- }
- } else {
- nextentry= ads->searchlist[qu->search_pos++];
- }
- }
-
- qu->search_vb.used= qu->search_origlen;
- if (nextentry) {
- if (!adns__vbuf_append(&qu->search_vb,".",1) ||
- !adns__vbuf_appendstr(&qu->search_vb,nextentry)) {
- stat= adns_s_nomemory; goto x_fail;
- }
- }
-
- free(qu->query_dgram);
- qu->query_dgram= 0; qu->query_dglen= 0;
-
- query_simple(ads,qu, qu->search_vb.buf, qu->search_vb.used, qu->typei, qu->flags, now);
- return;
-
-x_fail:
- adns__query_fail(qu,stat);
-}
-
-static int save_owner(adns_query qu, const char *owner, int ol) {
- /* Returns 1 if OK, otherwise there was no memory. */
- adns_answer *ans;
-
- ans= qu->answer;
- assert(!ans->owner);
-
- ans->owner= adns__alloc_preserved(qu,ol+1); if (!ans->owner) return 0;
-
- memcpy(ans->owner,owner,ol);
- ans->owner[ol]= 0;
- return 1;
-}
-
-int adns_submit(adns_state ads,
- const char *owner,
- adns_rrtype type,
- adns_queryflags flags,
- void *context,
- adns_query *query_r) {
- int r, ol, ndots;
- adns_status stat;
- const typeinfo *typei;
- struct timeval now;
- adns_query qu;
- const char *p;
-
- adns__consistency(ads,0,cc_entex);
-
- typei= adns__findtype(type);
- if (!typei) return ENOSYS;
-
- r= gettimeofday(&now,0); if (r) goto x_errno;
- qu= query_alloc(ads,typei,flags,now); if (!qu) goto x_errno;
-
- qu->ctx.ext= context;
- qu->ctx.callback= 0;
- memset(&qu->ctx.info,0,sizeof(qu->ctx.info));
-
- *query_r= qu;
-
- ol= strlen(owner);
- if (!ol) { stat= adns_s_querydomaininvalid; goto x_adnsfail; }
- if (ol>DNS_MAXDOMAIN+1) { stat= adns_s_querydomaintoolong; goto x_adnsfail; }
-
- if (ol>=1 && owner[ol-1]=='.' && (ol<2 || owner[ol-2]!='\\')) {
- flags &= ~adns_qf_search;
- qu->flags= flags;
- ol--;
- }
-
- if (flags & adns_qf_search) {
- r= adns__vbuf_append(&qu->search_vb,owner,ol);
- if (!r) { stat= adns_s_nomemory; goto x_adnsfail; }
-
- for (ndots=0, p=owner; (p= strchr(p,'.')); p++, ndots++);
- qu->search_doneabs= (ndots >= ads->searchndots) ? -1 : 0;
- qu->search_origlen= ol;
- adns__search_next(ads,qu,now);
- } else {
- if (flags & adns_qf_owner) {
- if (!save_owner(qu,owner,ol)) { stat= adns_s_nomemory; goto x_adnsfail; }
- }
- query_simple(ads,qu, owner,ol, typei,flags, now);
- }
- adns__autosys(ads,now);
- adns__consistency(ads,qu,cc_entex);
- return 0;
-
- x_adnsfail:
- adns__query_fail(qu,stat);
- adns__consistency(ads,qu,cc_entex);
- return 0;
-
- x_errno:
- r= errno;
- assert(r);
- adns__consistency(ads,0,cc_entex);
- return r;
-}
-
-int adns_submit_reverse(adns_state ads,
- const struct sockaddr *addr,
- adns_rrtype type,
- adns_queryflags flags,
- void *context,
- adns_query *query_r) {
- const unsigned char *iaddr;
- char buf[30];
-
- if (type != adns_r_ptr && type != adns_r_ptr_raw) return EINVAL;
- flags &= ~adns_qf_search;
-
- if (addr->sa_family != AF_INET) return ENOSYS;
- iaddr= (const unsigned char*) &(((const struct sockaddr_in*)addr) -> sin_addr);
-
- sprintf(buf, "%d.%d.%d.%d.in-addr.arpa",
- iaddr[3], iaddr[2], iaddr[1], iaddr[0]);
-
- return adns_submit(ads,buf,type,flags,context,query_r);
-}
-
-int adns_synchronous(adns_state ads,
- const char *owner,
- adns_rrtype type,
- adns_queryflags flags,
- adns_answer **answer_r) {
- adns_query qu;
- int r;
-
- r= adns_submit(ads,owner,type,flags,0,&qu);
- if (r) return r;
-
- r= adns_wait(ads,&qu,answer_r,0);
- if (r) adns_cancel(qu);
-
- return r;
-}
-
-static void *alloc_common(adns_query qu, size_t sz) {
- allocnode *an;
-
- if (!sz) return qu; /* Any old pointer will do */
- assert(!qu->final_allocspace);
- an= malloc(MEM_ROUND(MEM_ROUND(sizeof(*an)) + sz));
- if (!an) return 0;
- LIST_LINK_TAIL(qu->allocations,an);
- return (byte*)an + MEM_ROUND(sizeof(*an));
-}
-
-void *adns__alloc_interim(adns_query qu, size_t sz) {
- void *rv;
-
- sz= MEM_ROUND(sz);
- rv= alloc_common(qu,sz);
- if (!rv) return 0;
- qu->interim_allocd += sz;
- return rv;
-}
-
-void *adns__alloc_preserved(adns_query qu, size_t sz) {
- void *rv;
-
- sz= MEM_ROUND(sz);
- rv= adns__alloc_interim(qu,sz);
- if (!rv) return 0;
- qu->preserved_allocd += sz;
- return rv;
-}
-
-void *adns__alloc_mine(adns_query qu, size_t sz) {
- return alloc_common(qu,MEM_ROUND(sz));
-}
-
-void adns__transfer_interim(adns_query from, adns_query to, void *block, size_t sz) {
- allocnode *an;
-
- if (!block) return;
- an= (void*)((byte*)block - MEM_ROUND(sizeof(*an)));
-
- assert(!to->final_allocspace);
- assert(!from->final_allocspace);
-
- LIST_UNLINK(from->allocations,an);
- LIST_LINK_TAIL(to->allocations,an);
-
- from->interim_allocd -= sz;
- to->interim_allocd += sz;
-
- if (to->expires > from->expires) to->expires= from->expires;
-}
-
-void *adns__alloc_final(adns_query qu, size_t sz) {
- /* When we're in the _final stage, we _subtract_ from interim_alloc'd
- * each allocation, and use final_allocspace to point to the next free
- * bit.
- */
- void *rp;
-
- sz= MEM_ROUND(sz);
- rp= qu->final_allocspace;
- assert(rp);
- qu->interim_allocd -= sz;
- assert(qu->interim_allocd>=0);
- qu->final_allocspace= (byte*)rp + sz;
- return rp;
-}
-
-static void cancel_children(adns_query qu) {
- adns_query cqu, ncqu;
-
- for (cqu= qu->children.head; cqu; cqu= ncqu) {
- ncqu= cqu->siblings.next;
- adns_cancel(cqu);
- }
-}
-
-void adns__reset_preserved(adns_query qu) {
- assert(!qu->final_allocspace);
- cancel_children(qu);
- qu->answer->nrrs= 0;
- qu->answer->rrs.untyped= 0;
- qu->interim_allocd= qu->preserved_allocd;
-}
-
-static void free_query_allocs(adns_query qu) {
- allocnode *an, *ann;
-
- cancel_children(qu);
- for (an= qu->allocations.head; an; an= ann) { ann= an->next; free(an); }
- LIST_INIT(qu->allocations);
- adns__vbuf_free(&qu->vb);
- adns__vbuf_free(&qu->search_vb);
- free(qu->query_dgram);
-}
-
-void adns_cancel(adns_query qu) {
- adns_state ads;
-
- ads= qu->ads;
- adns__consistency(ads,qu,cc_entex);
- if (qu->parent) LIST_UNLINK_PART(qu->parent->children,qu,siblings.);
- switch (qu->state) {
- case query_tosend:
- LIST_UNLINK(ads->udpw,qu);
- break;
- case query_tcpw:
- LIST_UNLINK(ads->tcpw,qu);
- break;
- case query_childw:
- LIST_UNLINK(ads->childw,qu);
- break;
- case query_done:
- LIST_UNLINK(ads->output,qu);
- break;
- default:
- abort();
- }
- free_query_allocs(qu);
- free(qu->answer);
- free(qu);
- adns__consistency(ads,0,cc_entex);
-}
-
-void adns__update_expires(adns_query qu, unsigned long ttl, struct timeval now) {
- time_t max;
-
- assert(ttl <= MAXTTLBELIEVE);
- max= now.tv_sec + ttl;
- if (qu->expires < max) return;
- qu->expires= max;
-}
-
-static void makefinal_query(adns_query qu) {
- adns_answer *ans;
- int rrn;
-
- ans= qu->answer;
-
- if (qu->interim_allocd) {
- ans= realloc(qu->answer, MEM_ROUND(MEM_ROUND(sizeof(*ans)) + qu->interim_allocd));
- if (!ans) goto x_nomem;
- qu->answer= ans;
- }
-
- qu->final_allocspace= (byte*)ans + MEM_ROUND(sizeof(*ans));
- adns__makefinal_str(qu,&ans->cname);
- adns__makefinal_str(qu,&ans->owner);
-
- if (ans->nrrs) {
- adns__makefinal_block(qu, &ans->rrs.untyped, ans->nrrs*ans->rrsz);
-
- for (rrn=0; rrn<ans->nrrs; rrn++)
- qu->typei->makefinal(qu, ans->rrs.bytes + rrn*ans->rrsz);
- }
-
- free_query_allocs(qu);
- return;
-
- x_nomem:
- qu->preserved_allocd= 0;
- qu->answer->cname= 0;
- qu->answer->owner= 0;
- adns__reset_preserved(qu); /* (but we just threw away the preserved stuff) */
-
- qu->answer->status= adns_s_nomemory;
- free_query_allocs(qu);
-}
-
-void adns__query_done(adns_query qu) {
- adns_answer *ans;
- adns_query parent;
-
- cancel_children(qu);
-
- qu->id= -1;
- ans= qu->answer;
-
- if (qu->flags & adns_qf_owner && qu->flags & adns_qf_search &&
- ans->status != adns_s_nomemory) {
- if (!save_owner(qu, qu->search_vb.buf, qu->search_vb.used)) {
- adns__query_fail(qu,adns_s_nomemory);
- return;
- }
- }
-
- if (ans->nrrs && qu->typei->diff_needswap) {
- if (!adns__vbuf_ensure(&qu->vb,qu->typei->rrsz)) {
- adns__query_fail(qu,adns_s_nomemory);
- return;
- }
- adns__isort(ans->rrs.bytes, ans->nrrs, ans->rrsz,
- qu->vb.buf,
- (int(*)(void*, const void*, const void*))qu->typei->diff_needswap,
- qu->ads);
- }
-
- ans->expires= qu->expires;
- parent= qu->parent;
- if (parent) {
- LIST_UNLINK_PART(parent->children,qu,siblings.);
- LIST_UNLINK(qu->ads->childw,parent);
- qu->ctx.callback(parent,qu);
- free_query_allocs(qu);
- free(qu->answer);
- free(qu);
- } else {
- makefinal_query(qu);
- LIST_LINK_TAIL(qu->ads->output,qu);
- qu->state= query_done;
- }
-}
-
-void adns__query_fail(adns_query qu, adns_status stat) {
- adns__reset_preserved(qu);
- qu->answer->status= stat;
- adns__query_done(qu);
-}
-
-void adns__makefinal_str(adns_query qu, char **strp) {
- int l;
- char *before, *after;
-
- before= *strp;
- if (!before) return;
- l= strlen(before)+1;
- after= adns__alloc_final(qu,l);
- memcpy(after,before,l);
- *strp= after;
-}
-
-void adns__makefinal_block(adns_query qu, void **blpp, size_t sz) {
- void *before, *after;
-
- before= *blpp;
- if (!before) return;
- after= adns__alloc_final(qu,sz);
- memcpy(after,before,sz);
- *blpp= after;
-}
diff --git a/adns-0.6/src/reply.c b/adns-0.6/src/reply.c
deleted file mode 100644
index 246d52d..0000000
--- a/adns-0.6/src/reply.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * reply.c
- * - main handling and parsing routine for received datagrams
- */
-/*
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <stdlib.h>
-
-#include "internal.h"
-
-void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
- int serv, int viatcp, struct timeval now) {
- int cbyte, rrstart, wantedrrs, rri, foundsoa, foundns, cname_here;
- int id, f1, f2, qdcount, ancount, nscount, arcount;
- int flg_ra, flg_rd, flg_tc, flg_qr, opcode;
- int rrtype, rrclass, rdlength, rdstart;
- int anstart, nsstart, arstart;
- int ownermatched, l, nrrs;
- unsigned long ttl, soattl;
- const typeinfo *typei;
- adns_query qu, nqu;
- dns_rcode rcode;
- adns_status st;
- vbuf tempvb;
- byte *newquery, *rrsdata;
- parseinfo pai;
-
- if (dglen<DNS_HDRSIZE) {
- adns__diag(ads,serv,0,"received datagram too short for message header (%d)",dglen);
- return;
- }
- cbyte= 0;
- GET_W(cbyte,id);
- GET_B(cbyte,f1);
- GET_B(cbyte,f2);
- GET_W(cbyte,qdcount);
- GET_W(cbyte,ancount);
- GET_W(cbyte,nscount);
- GET_W(cbyte,arcount);
- assert(cbyte == DNS_HDRSIZE);
-
- flg_qr= f1&0x80;
- opcode= (f1&0x78)>>3;
- flg_tc= f1&0x02;
- flg_rd= f1&0x01;
- flg_ra= f2&0x80;
- rcode= (f2&0x0f);
-
- cname_here= 0;
-
- if (!flg_qr) {
- adns__diag(ads,serv,0,"server sent us a query, not a response");
- return;
- }
- if (opcode) {
- adns__diag(ads,serv,0,"server sent us unknown opcode %d (wanted 0=QUERY)",opcode);
- return;
- }
- if (!qdcount) {
- adns__diag(ads,serv,0,"server sent reply without quoting our question");
- return;
- } else if (qdcount>1) {
- adns__diag(ads,serv,0,"server claimed to answer %d questions with one message",
- qdcount);
- return;
- }
- for (qu= viatcp ? ads->tcpw.head : ads->udpw.head; qu; qu= nqu) {
- nqu= qu->next;
- if (qu->id != id) continue;
- if (dglen < qu->query_dglen) continue;
- if (memcmp(qu->query_dgram+DNS_HDRSIZE,
- dgram+DNS_HDRSIZE,
- qu->query_dglen-DNS_HDRSIZE))
- continue;
- if (viatcp) {
- assert(qu->state == query_tcpw);
- } else {
- assert(qu->state == query_tosend);
- if (!(qu->udpsent & (1<<serv))) continue;
- }
- break;
- }
- if (!qu) {
- if (ads->iflags & adns_if_debug) {
- adns__vbuf_init(&tempvb);
- adns__debug(ads,serv,0,"reply not found, id %02x, query owner %s",
- id, adns__diag_domain(ads,serv,0,&tempvb,dgram,dglen,DNS_HDRSIZE));
- adns__vbuf_free(&tempvb);
- }
- return;
- }
- anstart= qu->query_dglen;
- arstart= -1;
-
- if (viatcp) LIST_UNLINK(ads->tcpw,qu);
- else LIST_UNLINK(ads->udpw,qu);
- /* We're definitely going to do something with this query now */
-
- switch (rcode) {
- case rcode_noerror:
- case rcode_nxdomain:
- break;
- case rcode_formaterror:
- adns__warn(ads,serv,qu,"server cannot understand our query (Format Error)");
- adns__query_fail(qu,adns_s_rcodeformaterror);
- return;
- case rcode_servfail:
- adns__query_fail(qu,adns_s_rcodeservfail);
- return;
- case rcode_notimp:
- adns__warn(ads,serv,qu,"server claims not to implement our query");
- adns__query_fail(qu,adns_s_rcodenotimplemented);
- return;
- case rcode_refused:
- adns__warn(ads,serv,qu,"server refused our query");
- adns__query_fail(qu,adns_s_rcoderefused);
- return;
- default:
- adns__warn(ads,serv,qu,"server gave unknown response code %d",rcode);
- adns__query_fail(qu,adns_s_rcodeunknown);
- return;
- }
-
- /* Now, take a look at the answer section, and see if it is complete.
- * If it has any CNAMEs we stuff them in the answer.
- */
- wantedrrs= 0;
- cbyte= anstart;
- for (rri= 0; rri<ancount; rri++) {
- rrstart= cbyte;
- st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
- &rrtype,&rrclass,&ttl, &rdlength,&rdstart,
- &ownermatched);
- if (st) { adns__query_fail(qu,st); return; }
- if (rrtype == -1) goto x_truncated;
-
- if (rrclass != DNS_CLASS_IN) {
- adns__diag(ads,serv,qu,"ignoring answer RR with wrong class %d (expected IN=%d)",
- rrclass,DNS_CLASS_IN);
- continue;
- }
- if (!ownermatched) {
- if (ads->iflags & adns_if_debug) {
- adns__debug(ads,serv,qu,"ignoring RR with an unexpected owner %s",
- adns__diag_domain(ads,serv,qu, &qu->vb, dgram,dglen,rrstart));
- }
- continue;
- }
- if (rrtype == adns_r_cname &&
- (qu->typei->type & adns__rrt_typemask) != adns_r_cname) {
- if (qu->flags & adns_qf_cname_forbid) {
- adns__query_fail(qu,adns_s_prohibitedcname);
- return;
- } else if (qu->cname_dgram) { /* Ignore second and subsequent CNAME(s) */
- adns__debug(ads,serv,qu,"allegedly canonical name %s is actually alias for %s",
- qu->answer->cname,
- adns__diag_domain(ads,serv,qu, &qu->vb, dgram,dglen,rdstart));
- adns__query_fail(qu,adns_s_prohibitedcname);
- return;
- } else if (wantedrrs) { /* Ignore CNAME(s) after RR(s). */
- adns__debug(ads,serv,qu,"ignoring CNAME (to %s) coexisting with RR",
- adns__diag_domain(ads,serv,qu, &qu->vb, dgram,dglen,rdstart));
- } else {
- qu->cname_begin= rdstart;
- qu->cname_dglen= dglen;
- st= adns__parse_domain(ads,serv,qu, &qu->vb,
- qu->flags & adns_qf_quoteok_cname ? pdf_quoteok : 0,
- dgram,dglen, &rdstart,rdstart+rdlength);
- if (!qu->vb.used) goto x_truncated;
- if (st) { adns__query_fail(qu,st); return; }
- l= strlen(qu->vb.buf)+1;
- qu->answer->cname= adns__alloc_preserved(qu,l);
- if (!qu->answer->cname) { adns__query_fail(qu,adns_s_nomemory); return; }
-
- qu->cname_dgram= adns__alloc_mine(qu,dglen);
- memcpy(qu->cname_dgram,dgram,dglen);
-
- memcpy(qu->answer->cname,qu->vb.buf,l);
- cname_here= 1;
- adns__update_expires(qu,ttl,now);
- /* If we find the answer section truncated after this point we restart
- * the query at the CNAME; if beforehand then we obviously have to use
- * TCP. If there is no truncation we can use the whole answer if
- * it contains the relevant info.
- */
- }
- } else if (rrtype == (qu->typei->type & adns__rrt_typemask)) {
- wantedrrs++;
- } else {
- adns__debug(ads,serv,qu,"ignoring answer RR with irrelevant type %d",rrtype);
- }
- }
-
- /* We defer handling truncated responses here, in case there was a CNAME
- * which we could use.
- */
- if (flg_tc) goto x_truncated;
-
- nsstart= cbyte;
-
- if (!wantedrrs) {
- /* Oops, NODATA or NXDOMAIN or perhaps a referral (which would be a problem) */
-
- /* RFC2308: NODATA has _either_ a SOA _or_ _no_ NS records in authority section */
- foundsoa= 0; soattl= 0; foundns= 0;
- for (rri= 0; rri<nscount; rri++) {
- rrstart= cbyte;
- st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
- &rrtype,&rrclass,&ttl, &rdlength,&rdstart, 0);
- if (st) { adns__query_fail(qu,st); return; }
- if (rrtype==-1) goto x_truncated;
- if (rrclass != DNS_CLASS_IN) {
- adns__diag(ads,serv,qu,
- "ignoring authority RR with wrong class %d (expected IN=%d)",
- rrclass,DNS_CLASS_IN);
- continue;
- }
- if (rrtype == adns_r_soa_raw) { foundsoa= 1; soattl= ttl; break; }
- else if (rrtype == adns_r_ns_raw) { foundns= 1; }
- }
-
- if (rcode == rcode_nxdomain) {
- /* We still wanted to look for the SOA so we could find the TTL. */
- adns__update_expires(qu,soattl,now);
-
- if (qu->flags & adns_qf_search) {
- adns__search_next(ads,qu,now);
- } else {
- adns__query_fail(qu,adns_s_nxdomain);
- }
- return;
- }
-
- if (foundsoa || !foundns) {
- /* Aha ! A NODATA response, good. */
- adns__update_expires(qu,soattl,now);
- adns__query_fail(qu,adns_s_nodata);
- return;
- }
-
- /* Now what ? No relevant answers, no SOA, and at least some NS's.
- * Looks like a referral. Just one last chance ... if we came across
- * a CNAME in this datagram then we should probably do our own CNAME
- * lookup now in the hope that we won't get a referral again.
- */
- if (cname_here) goto x_restartquery;
-
- /* Bloody hell, I thought we asked for recursion ? */
- if (flg_rd) {
- adns__diag(ads,serv,qu,"server thinks we didn't ask for recursive lookup");
- }
- if (!flg_ra) {
- adns__diag(ads,serv,qu,"server is not willing to do recursive lookups for us");
- adns__query_fail(qu,adns_s_norecurse);
- } else {
- adns__diag(ads,serv,qu,"server claims to do recursion, but gave us a referral");
- adns__query_fail(qu,adns_s_invalidresponse);
- }
- return;
- }
-
- /* Now, we have some RRs which we wanted. */
-
- qu->answer->rrs.untyped= adns__alloc_interim(qu,qu->typei->rrsz*wantedrrs);
- if (!qu->answer->rrs.untyped) { adns__query_fail(qu,adns_s_nomemory); return; }
-
- typei= qu->typei;
- cbyte= anstart;
- rrsdata= qu->answer->rrs.bytes;
-
- pai.ads= qu->ads;
- pai.qu= qu;
- pai.serv= serv;
- pai.dgram= dgram;
- pai.dglen= dglen;
- pai.nsstart= nsstart;
- pai.nscount= nscount;
- pai.arcount= arcount;
- pai.now= now;
-
- for (rri=0, nrrs=0; rri<ancount; rri++) {
- st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
- &rrtype,&rrclass,&ttl, &rdlength,&rdstart,
- &ownermatched);
- assert(!st); assert(rrtype != -1);
- if (rrclass != DNS_CLASS_IN ||
- rrtype != (qu->typei->type & adns__rrt_typemask) ||
- !ownermatched)
- continue;
- adns__update_expires(qu,ttl,now);
- st= typei->parse(&pai, rdstart,rdstart+rdlength, rrsdata+nrrs*typei->rrsz);
- if (st) { adns__query_fail(qu,st); return; }
- if (rdstart==-1) goto x_truncated;
- nrrs++;
- }
- assert(nrrs==wantedrrs);
- qu->answer->nrrs= nrrs;
-
- /* This may have generated some child queries ... */
- if (qu->children.head) {
- qu->state= query_childw;
- LIST_LINK_TAIL(ads->childw,qu);
- return;
- }
- adns__query_done(qu);
- return;
-
- x_truncated:
-
- if (!flg_tc) {
- adns__diag(ads,serv,qu,"server sent datagram which points outside itself");
- adns__query_fail(qu,adns_s_invalidresponse);
- return;
- }
- qu->flags |= adns_qf_usevc;
-
- x_restartquery:
- if (qu->cname_dgram) {
- st= adns__mkquery_frdgram(qu->ads,&qu->vb,&qu->id,
- qu->cname_dgram, qu->cname_dglen, qu->cname_begin,
- qu->typei->type, qu->flags);
- if (st) { adns__query_fail(qu,st); return; }
-
- newquery= realloc(qu->query_dgram,qu->vb.used);
- if (!newquery) { adns__query_fail(qu,adns_s_nomemory); return; }
-
- qu->query_dgram= newquery;
- qu->query_dglen= qu->vb.used;
- memcpy(newquery,qu->vb.buf,qu->vb.used);
- }
-
- if (qu->state == query_tcpw) qu->state= query_tosend;
- qu->retries= 0;
- adns__reset_preserved(qu);
- adns__query_send(qu,now);
-}
diff --git a/adns-0.6/src/setup.c b/adns-0.6/src/setup.c
deleted file mode 100644
index ac88c33..0000000
--- a/adns-0.6/src/setup.c
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- * setup.c
- * - configuration file parsing
- * - management of global state
- */
-/*
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "internal.h"
-
-static void readconfig(adns_state ads, const char *filename, int warnmissing);
-
-static void addserver(adns_state ads, struct in_addr addr) {
- int i;
- struct server *ss;
-
- for (i=0; i<ads->nservers; i++) {
- if (ads->servers[i].addr.s_addr == addr.s_addr) {
- adns__debug(ads,-1,0,"duplicate nameserver %s ignored",inet_ntoa(addr));
- return;
- }
- }
-
- if (ads->nservers>=MAXSERVERS) {
- adns__diag(ads,-1,0,"too many nameservers, ignoring %s",inet_ntoa(addr));
- return;
- }
-
- ss= ads->servers+ads->nservers;
- ss->addr= addr;
- ads->nservers++;
-}
-
-static void freesearchlist(adns_state ads) {
- if (ads->nsearchlist) free(*ads->searchlist);
- free(ads->searchlist);
-}
-
-static void saveerr(adns_state ads, int en) {
- if (!ads->configerrno) ads->configerrno= en;
-}
-
-static void configparseerr(adns_state ads, const char *fn, int lno,
- const char *fmt, ...) {
- va_list al;
-
- saveerr(ads,EINVAL);
- if (!ads->diagfile || (ads->iflags & adns_if_noerrprint)) return;
-
- if (lno==-1) fprintf(ads->diagfile,"adns: %s: ",fn);
- else fprintf(ads->diagfile,"adns: %s:%d: ",fn,lno);
- va_start(al,fmt);
- vfprintf(ads->diagfile,fmt,al);
- va_end(al);
- fputc('\n',ads->diagfile);
-}
-
-static int nextword(const char **bufp_io, const char **word_r, int *l_r) {
- const char *p, *q;
-
- p= *bufp_io;
- while (ctype_whitespace(*p)) p++;
- if (!*p) return 0;
-
- q= p;
- while (*q && !ctype_whitespace(*q)) q++;
-
- *l_r= q-p;
- *word_r= p;
- *bufp_io= q;
-
- return 1;
-}
-
-static void ccf_nameserver(adns_state ads, const char *fn, int lno, const char *buf) {
- struct in_addr ia;
-
- if (!inet_aton(buf,&ia)) {
- configparseerr(ads,fn,lno,"invalid nameserver address `%s'",buf);
- return;
- }
- adns__debug(ads,-1,0,"using nameserver %s",inet_ntoa(ia));
- addserver(ads,ia);
-}
-
-static void ccf_search(adns_state ads, const char *fn, int lno, const char *buf) {
- const char *bufp, *word;
- char *newchars, **newptrs, **pp;
- int count, tl, l;
-
- if (!buf) return;
-
- bufp= buf;
- count= 0;
- tl= 0;
- while (nextword(&bufp,&word,&l)) { count++; tl += l+1; }
-
- newptrs= malloc(sizeof(char*)*count); if (!newptrs) { saveerr(ads,errno); return; }
- newchars= malloc(tl); if (!newchars) { saveerr(ads,errno); free(newptrs); return; }
-
- bufp= buf;
- pp= newptrs;
- while (nextword(&bufp,&word,&l)) {
- *pp++= newchars;
- memcpy(newchars,word,l);
- newchars += l;
- *newchars++ = 0;
- }
-
- freesearchlist(ads);
- ads->nsearchlist= count;
- ads->searchlist= newptrs;
-}
-
-static void ccf_sortlist(adns_state ads, const char *fn, int lno, const char *buf) {
- const char *word;
- char tbuf[200], *slash, *ep;
- struct in_addr base, mask;
- int l;
- unsigned long initial, baselocal;
-
- if (!buf) return;
-
- ads->nsortlist= 0;
- while (nextword(&buf,&word,&l)) {
- if (ads->nsortlist >= MAXSORTLIST) {
- adns__diag(ads,-1,0,"too many sortlist entries, ignoring %.*s onwards",l,word);
- return;
- }
-
- if (l >= sizeof(tbuf)) {
- configparseerr(ads,fn,lno,"sortlist entry `%.*s' too long",l,word);
- continue;
- }
-
- memcpy(tbuf,word,l); tbuf[l]= 0;
- slash= strchr(tbuf,'/');
- if (slash) *slash++= 0;
-
- if (!inet_aton(tbuf,&base)) {
- configparseerr(ads,fn,lno,"invalid address `%s' in sortlist",tbuf);
- continue;
- }
-
- if (slash) {
- if (strchr(slash,'.')) {
- if (!inet_aton(slash,&mask)) {
- configparseerr(ads,fn,lno,"invalid mask `%s' in sortlist",slash);
- continue;
- }
- if (base.s_addr & ~mask.s_addr) {
- configparseerr(ads,fn,lno,
- "mask `%s' in sortlist overlaps address `%s'",slash,tbuf);
- continue;
- }
- } else {
- initial= strtoul(slash,&ep,10);
- if (*ep || initial>32) {
- configparseerr(ads,fn,lno,"mask length `%s' invalid",slash);
- continue;
- }
- mask.s_addr= htonl((0x0ffffffffUL) << (32-initial));
- }
- } else {
- baselocal= ntohl(base.s_addr);
- if (!baselocal & 0x080000000UL) /* class A */
- mask.s_addr= htonl(0x0ff000000UL);
- else if ((baselocal & 0x0c0000000UL) == 0x080000000UL)
- mask.s_addr= htonl(0x0ffff0000UL); /* class B */
- else if ((baselocal & 0x0f0000000UL) == 0x0e0000000UL)
- mask.s_addr= htonl(0x0ff000000UL); /* class C */
- else {
- configparseerr(ads,fn,lno,
- "network address `%s' in sortlist is not in classed ranges,"
- " must specify mask explicitly", tbuf);
- continue;
- }
- }
-
- ads->sortlist[ads->nsortlist].base= base;
- ads->sortlist[ads->nsortlist].mask= mask;
- ads->nsortlist++;
- }
-}
-
-static void ccf_options(adns_state ads, const char *fn, int lno, const char *buf) {
- const char *word;
- char *ep;
- unsigned long v;
- int l;
-
- if (!buf) return;
-
- while (nextword(&buf,&word,&l)) {
- if (l==5 && !memcmp(word,"debug",5)) {
- ads->iflags |= adns_if_debug;
- continue;
- }
- if (l>=6 && !memcmp(word,"ndots:",6)) {
- v= strtoul(word+6,&ep,10);
- if (l==6 || ep != word+l || v > INT_MAX) {
- configparseerr(ads,fn,lno,"option `%.*s' malformed or has bad value",l,word);
- continue;
- }
- ads->searchndots= v;
- continue;
- }
- if (l>=12 && !memcmp(word,"adns_checkc:",12)) {
- if (!strcmp(word+12,"none")) {
- ads->iflags &= ~adns_if_checkc_freq;
- ads->iflags |= adns_if_checkc_entex;
- } else if (!strcmp(word+12,"entex")) {
- ads->iflags &= ~adns_if_checkc_freq;
- ads->iflags |= adns_if_checkc_entex;
- } else if (!strcmp(word+12,"freq")) {
- ads->iflags |= adns_if_checkc_freq;
- } else {
- configparseerr(ads,fn,lno, "option adns_checkc has bad value `%s' "
- "(must be none, entex or freq", word+12);
- }
- continue;
- }
- adns__diag(ads,-1,0,"%s:%d: unknown option `%.*s'", fn,lno, l,word);
- }
-}
-
-static void ccf_clearnss(adns_state ads, const char *fn, int lno, const char *buf) {
- ads->nservers= 0;
-}
-
-static void ccf_include(adns_state ads, const char *fn, int lno, const char *buf) {
- if (!*buf) {
- configparseerr(ads,fn,lno,"`include' directive with no filename");
- return;
- }
- readconfig(ads,buf,1);
-}
-
-static const struct configcommandinfo {
- const char *name;
- void (*fn)(adns_state ads, const char *fn, int lno, const char *buf);
-} configcommandinfos[]= {
- { "nameserver", ccf_nameserver },
- { "domain", ccf_search },
- { "search", ccf_search },
- { "sortlist", ccf_sortlist },
- { "options", ccf_options },
- { "clearnameservers", ccf_clearnss },
- { "include", ccf_include },
- { 0 }
-};
-
-typedef union {
- FILE *file;
- const char *text;
-} getline_ctx;
-
-static int gl_file(adns_state ads, getline_ctx *src_io, const char *filename,
- int lno, char *buf, int buflen) {
- FILE *file= src_io->file;
- int c, i;
- char *p;
-
- p= buf;
- buflen--;
- i= 0;
-
- for (;;) { /* loop over chars */
- if (i == buflen) {
- adns__diag(ads,-1,0,"%s:%d: line too long, ignored",filename,lno);
- goto x_badline;
- }
- c= getc(file);
- if (!c) {
- adns__diag(ads,-1,0,"%s:%d: line contains nul, ignored",filename,lno);
- goto x_badline;
- } else if (c == '\n') {
- break;
- } else if (c == EOF) {
- if (ferror(file)) {
- saveerr(ads,errno);
- adns__diag(ads,-1,0,"%s:%d: read error: %s",filename,lno,strerror(errno));
- return -1;
- }
- if (!i) return -1;
- break;
- } else {
- *p++= c;
- i++;
- }
- }
-
- *p++= 0;
- return i;
-
- x_badline:
- saveerr(ads,EINVAL);
- while ((c= getc(file)) != EOF && c != '\n');
- return -2;
-}
-
-static int gl_text(adns_state ads, getline_ctx *src_io, const char *filename,
- int lno, char *buf, int buflen) {
- const char *cp= src_io->text;
- int l;
-
- if (!cp || !*cp) return -1;
-
- if (*cp == ';' || *cp == '\n') cp++;
- l= strcspn(cp,";\n");
- src_io->text = cp+l;
-
- if (l >= buflen) {
- adns__diag(ads,-1,0,"%s:%d: line too long, ignored",filename,lno);
- saveerr(ads,EINVAL);
- return -2;
- }
-
- memcpy(buf,cp,l);
- buf[l]= 0;
- return l;
-}
-
-static void readconfiggeneric(adns_state ads, const char *filename,
- int (*getline)(adns_state ads, getline_ctx*,
- const char *filename, int lno,
- char *buf, int buflen),
- /* Returns >=0 for success, -1 for EOF or error
- * (error will have been reported), or -2 for
- * bad line was encountered, try again.
- */
- getline_ctx gl_ctx) {
- char linebuf[2000], *p, *q;
- int lno, l, dirl;
- const struct configcommandinfo *ccip;
-
- for (lno=1;
- (l= getline(ads,&gl_ctx, filename,lno, linebuf,sizeof(linebuf))) != -1;
- lno++) {
- if (l == -2) continue;
- while (l>0 && ctype_whitespace(linebuf[l-1])) l--;
- linebuf[l]= 0;
- p= linebuf;
- while (ctype_whitespace(*p)) p++;
- if (*p == '#' || !*p) continue;
- q= p;
- while (*q && !ctype_whitespace(*q)) q++;
- dirl= q-p;
- for (ccip=configcommandinfos;
- ccip->name && !(strlen(ccip->name)==dirl && !memcmp(ccip->name,p,q-p));
- ccip++);
- if (!ccip->name) {
- adns__diag(ads,-1,0,"%s:%d: unknown configuration directive `%.*s'",
- filename,lno,q-p,p);
- continue;
- }
- while (ctype_whitespace(*q)) q++;
- ccip->fn(ads,filename,lno,q);
- }
-}
-
-static const char *instrum_getenv(adns_state ads, const char *envvar) {
- const char *value;
-
- value= getenv(envvar);
- if (!value) adns__debug(ads,-1,0,"environment variable %s not set",envvar);
- else adns__debug(ads,-1,0,"environment variable %s set to `%s'",envvar,value);
- return value;
-}
-
-static void readconfig(adns_state ads, const char *filename, int warnmissing) {
- getline_ctx gl_ctx;
-
- gl_ctx.file= fopen(filename,"r");
- if (!gl_ctx.file) {
- if (errno == ENOENT) {
- if (warnmissing)
- adns__debug(ads,-1,0,"configuration file `%s' does not exist",filename);
- return;
- }
- saveerr(ads,errno);
- adns__diag(ads,-1,0,"cannot open configuration file `%s': %s",
- filename,strerror(errno));
- return;
- }
-
- readconfiggeneric(ads,filename,gl_file,gl_ctx);
-
- fclose(gl_ctx.file);
-}
-
-static void readconfigtext(adns_state ads, const char *text, const char *showname) {
- getline_ctx gl_ctx;
-
- gl_ctx.text= text;
- readconfiggeneric(ads,showname,gl_text,gl_ctx);
-}
-
-static void readconfigenv(adns_state ads, const char *envvar) {
- const char *filename;
-
- if (ads->iflags & adns_if_noenv) {
- adns__debug(ads,-1,0,"not checking environment variable `%s'",envvar);
- return;
- }
- filename= instrum_getenv(ads,envvar);
- if (filename) readconfig(ads,filename,1);
-}
-
-static void readconfigenvtext(adns_state ads, const char *envvar) {
- const char *textdata;
-
- if (ads->iflags & adns_if_noenv) {
- adns__debug(ads,-1,0,"not checking environment variable `%s'",envvar);
- return;
- }
- textdata= instrum_getenv(ads,envvar);
- if (textdata) readconfigtext(ads,textdata,envvar);
-}
-
-
-int adns__setnonblock(adns_state ads, int fd) {
- int r;
-
- r= fcntl(fd,F_GETFL,0); if (r<0) return errno;
- r |= O_NONBLOCK;
- r= fcntl(fd,F_SETFL,r); if (r<0) return errno;
- return 0;
-}
-
-static int init_begin(adns_state *ads_r, adns_initflags flags, FILE *diagfile) {
- adns_state ads;
-
- ads= malloc(sizeof(*ads)); if (!ads) return errno;
-
- ads->iflags= flags;
- ads->diagfile= diagfile;
- ads->configerrno= 0;
- LIST_INIT(ads->udpw);
- LIST_INIT(ads->tcpw);
- LIST_INIT(ads->childw);
- LIST_INIT(ads->output);
- ads->forallnext= 0;
- ads->nextid= 0x311f;
- ads->udpsocket= ads->tcpsocket= -1;
- adns__vbuf_init(&ads->tcpsend);
- adns__vbuf_init(&ads->tcprecv);
- ads->tcprecv_skip= 0;
- ads->nservers= ads->nsortlist= ads->nsearchlist= ads->tcpserver= 0;
- ads->searchndots= 1;
- ads->tcpstate= server_disconnected;
- timerclear(&ads->tcptimeout);
- ads->searchlist= 0;
-
- *ads_r= ads;
- return 0;
-}
-
-static int init_finish(adns_state ads) {
- struct in_addr ia;
- struct protoent *proto;
- int r;
-
- if (!ads->nservers) {
- if (ads->diagfile && ads->iflags & adns_if_debug)
- fprintf(ads->diagfile,"adns: no nameservers, using localhost\n");
- ia.s_addr= htonl(INADDR_LOOPBACK);
- addserver(ads,ia);
- }
-
- proto= getprotobyname("udp"); if (!proto) { r= ENOPROTOOPT; goto x_free; }
- ads->udpsocket= socket(AF_INET,SOCK_DGRAM,proto->p_proto);
- if (ads->udpsocket<0) { r= errno; goto x_free; }
-
- r= adns__setnonblock(ads,ads->udpsocket);
- if (r) { r= errno; goto x_closeudp; }
-
- return 0;
-
- x_closeudp:
- close(ads->udpsocket);
- x_free:
- free(ads);
- return r;
-}
-
-static void init_abort(adns_state ads) {
- if (ads->nsearchlist) {
- free(ads->searchlist[0]);
- free(ads->searchlist);
- }
- free(ads);
-}
-
-int adns_init(adns_state *ads_r, adns_initflags flags, FILE *diagfile) {
- adns_state ads;
- const char *res_options, *adns_res_options;
- int r;
-
- r= init_begin(&ads, flags, diagfile ? diagfile : stderr);
- if (r) return r;
-
- res_options= instrum_getenv(ads,"RES_OPTIONS");
- adns_res_options= instrum_getenv(ads,"ADNS_RES_OPTIONS");
- ccf_options(ads,"RES_OPTIONS",-1,res_options);
- ccf_options(ads,"ADNS_RES_OPTIONS",-1,adns_res_options);
-
- readconfig(ads,"/etc/resolv.conf",1);
- readconfig(ads,"/etc/resolv-adns.conf",0);
- readconfigenv(ads,"RES_CONF");
- readconfigenv(ads,"ADNS_RES_CONF");
-
- readconfigenvtext(ads,"RES_CONF_TEXT");
- readconfigenvtext(ads,"ADNS_RES_CONF_TEXT");
-
- ccf_options(ads,"RES_OPTIONS",-1,res_options);
- ccf_options(ads,"ADNS_RES_OPTIONS",-1,adns_res_options);
-
- ccf_search(ads,"LOCALDOMAIN",-1,instrum_getenv(ads,"LOCALDOMAIN"));
- ccf_search(ads,"ADNS_LOCALDOMAIN",-1,instrum_getenv(ads,"ADNS_LOCALDOMAIN"));
-
- if (ads->configerrno && ads->configerrno != EINVAL) {
- r= ads->configerrno;
- init_abort(ads);
- return r;
- }
-
- r= init_finish(ads);
- if (r) return r;
-
- adns__consistency(ads,0,cc_entex);
- *ads_r= ads;
- return 0;
-}
-
-int adns_init_strcfg(adns_state *ads_r, adns_initflags flags,
- FILE *diagfile, const char *configtext) {
- adns_state ads;
- int r;
-
- r= init_begin(&ads, flags, diagfile); if (r) return r;
-
- readconfigtext(ads,configtext,"<supplied configuration text>");
- if (ads->configerrno) {
- r= ads->configerrno;
- init_abort(ads);
- return r;
- }
-
- r= init_finish(ads); if (r) return r;
- adns__consistency(ads,0,cc_entex);
- *ads_r= ads;
- return 0;
-}
-
-
-void adns_finish(adns_state ads) {
- adns__consistency(ads,0,cc_entex);
- for (;;) {
- if (ads->udpw.head) adns_cancel(ads->udpw.head);
- else if (ads->tcpw.head) adns_cancel(ads->tcpw.head);
- else if (ads->childw.head) adns_cancel(ads->childw.head);
- else if (ads->output.head) adns_cancel(ads->output.head);
- else break;
- }
- close(ads->udpsocket);
- if (ads->tcpsocket >= 0) close(ads->tcpsocket);
- adns__vbuf_free(&ads->tcpsend);
- adns__vbuf_free(&ads->tcprecv);
- freesearchlist(ads);
- free(ads);
-}
-
-void adns_forallqueries_begin(adns_state ads) {
- adns__consistency(ads,0,cc_entex);
- ads->forallnext=
- ads->udpw.head ? ads->udpw.head :
- ads->tcpw.head ? ads->tcpw.head :
- ads->childw.head ? ads->childw.head :
- ads->output.head;
-}
-
-adns_query adns_forallqueries_next(adns_state ads, void **context_r) {
- adns_query qu, nqu;
-
- adns__consistency(ads,0,cc_entex);
- nqu= ads->forallnext;
- for (;;) {
- qu= nqu;
- if (!qu) return 0;
- if (qu->next) {
- nqu= qu->next;
- } else if (qu == ads->udpw.tail) {
- nqu=
- ads->tcpw.head ? ads->tcpw.head :
- ads->childw.head ? ads->childw.head :
- ads->output.head;
- } else if (qu == ads->tcpw.tail) {
- nqu=
- ads->childw.head ? ads->childw.head :
- ads->output.head;
- } else if (qu == ads->childw.tail) {
- nqu= ads->output.head;
- } else {
- nqu= 0;
- }
- if (!qu->parent) break;
- }
- ads->forallnext= nqu;
- if (context_r) *context_r= qu->ctx.ext;
- return qu;
-}
diff --git a/adns-0.6/src/transmit.c b/adns-0.6/src/transmit.c
deleted file mode 100644
index c669af6..0000000
--- a/adns-0.6/src/transmit.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * transmit.c
- * - construct queries
- * - send queries
- */
-/*
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <errno.h>
-
-#include <sys/types.h>
-#include <sys/uio.h>
-
-#include "internal.h"
-#include "tvarith.h"
-
-#define MKQUERY_START(vb) (rqp= (vb)->buf+(vb)->used)
-#define MKQUERY_ADDB(b) *rqp++= (b)
-#define MKQUERY_ADDW(w) (MKQUERY_ADDB(((w)>>8)&0x0ff), MKQUERY_ADDB((w)&0x0ff))
-#define MKQUERY_STOP(vb) ((vb)->used= rqp-(vb)->buf)
-
-static adns_status mkquery_header(adns_state ads, vbuf *vb, int *id_r, int qdlen) {
- int id;
- byte *rqp;
-
- if (!adns__vbuf_ensure(vb,DNS_HDRSIZE+qdlen+4)) return adns_s_nomemory;
-
- vb->used= 0;
- MKQUERY_START(vb);
-
- *id_r= id= (ads->nextid++) & 0x0ffff;
- MKQUERY_ADDW(id);
- MKQUERY_ADDB(0x01); /* QR=Q(0), OPCODE=QUERY(0000), !AA, !TC, RD */
- MKQUERY_ADDB(0x00); /* !RA, Z=000, RCODE=NOERROR(0000) */
- MKQUERY_ADDW(1); /* QDCOUNT=1 */
- MKQUERY_ADDW(0); /* ANCOUNT=0 */
- MKQUERY_ADDW(0); /* NSCOUNT=0 */
- MKQUERY_ADDW(0); /* ARCOUNT=0 */
-
- MKQUERY_STOP(vb);
-
- return adns_s_ok;
-}
-
-static adns_status mkquery_footer(vbuf *vb, adns_rrtype type) {
- byte *rqp;
-
- MKQUERY_START(vb);
- MKQUERY_ADDW(type & adns__rrt_typemask); /* QTYPE */
- MKQUERY_ADDW(DNS_CLASS_IN); /* QCLASS=IN */
- MKQUERY_STOP(vb);
- assert(vb->used <= vb->avail);
-
- return adns_s_ok;
-}
-
-adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r,
- const char *owner, int ol,
- const typeinfo *typei, adns_queryflags flags) {
- int ll, c, nlabs;
- byte label[255], *rqp;
- const char *p, *pe;
- adns_status st;
-
- st= mkquery_header(ads,vb,id_r,ol+2); if (st) return st;
-
- MKQUERY_START(vb);
-
- p= owner; pe= owner+ol;
- nlabs= 0;
- while (p!=pe) {
- ll= 0;
- while (p!=pe && (c= *p++)!='.') {
- if (c=='\\') {
- if (!(flags & adns_qf_quoteok_query)) return adns_s_querydomaininvalid;
- if (ctype_digit(p[0])) {
- if (ctype_digit(p[1]) && ctype_digit(p[2])) {
- c= (*p++ - '0')*100 + (*p++ - '0')*10 + (*p++ - '0');
- if (c >= 256) return adns_s_querydomaininvalid;
- } else {
- return adns_s_querydomaininvalid;
- }
- } else if (!(c= *p++)) {
- return adns_s_querydomaininvalid;
- }
- }
- if (!(flags & adns_qf_quoteok_query)) {
- if (c == '-') {
- if (!ll) return adns_s_querydomaininvalid;
- } else if (!ctype_alpha(c) && !ctype_digit(c)) {
- return adns_s_querydomaininvalid;
- }
- }
- if (ll == sizeof(label)) return adns_s_querydomaininvalid;
- label[ll++]= c;
- }
- if (!ll) return adns_s_querydomaininvalid;
- if (nlabs++ > 63) return adns_s_querydomaintoolong;
- MKQUERY_ADDB(ll);
- memcpy(rqp,label,ll); rqp+= ll;
- }
- MKQUERY_ADDB(0);
-
- MKQUERY_STOP(vb);
-
- st= mkquery_footer(vb,typei->type);
-
- return adns_s_ok;
-}
-
-adns_status adns__mkquery_frdgram(adns_state ads, vbuf *vb, int *id_r,
- const byte *qd_dgram, int qd_dglen, int qd_begin,
- adns_rrtype type, adns_queryflags flags) {
- byte *rqp;
- findlabel_state fls;
- int lablen, labstart;
- adns_status st;
-
- st= mkquery_header(ads,vb,id_r,qd_dglen); if (st) return st;
-
- MKQUERY_START(vb);
-
- adns__findlabel_start(&fls,ads,-1,0,qd_dgram,qd_dglen,qd_dglen,qd_begin,0);
- for (;;) {
- st= adns__findlabel_next(&fls,&lablen,&labstart); assert(!st);
- if (!lablen) break;
- assert(lablen<255);
- MKQUERY_ADDB(lablen);
- memcpy(rqp,qd_dgram+labstart,lablen);
- rqp+= lablen;
- }
- MKQUERY_ADDB(0);
-
- MKQUERY_STOP(vb);
-
- st= mkquery_footer(vb,type);
-
- return adns_s_ok;
-}
-
-void adns__querysend_tcp(adns_query qu, struct timeval now) {
- byte length[2];
- struct iovec iov[2];
- int wr, r;
- adns_state ads;
-
- if (qu->ads->tcpstate != server_ok) return;
-
- assert(qu->state == query_tcpw);
-
- length[0]= (qu->query_dglen&0x0ff00U) >>8;
- length[1]= (qu->query_dglen&0x0ff);
-
- ads= qu->ads;
- if (!adns__vbuf_ensure(&ads->tcpsend,ads->tcpsend.used+qu->query_dglen+2)) return;
-
- qu->retries++;
-
- /* Reset idle timeout. */
- ads->tcptimeout.tv_sec= ads->tcptimeout.tv_usec= 0;
-
- if (ads->tcpsend.used) {
- wr= 0;
- } else {
- iov[0].iov_base= length;
- iov[0].iov_len= 2;
- iov[1].iov_base= qu->query_dgram;
- iov[1].iov_len= qu->query_dglen;
- adns__sigpipe_protect(qu->ads);
- wr= writev(qu->ads->tcpsocket,iov,2);
- adns__sigpipe_unprotect(qu->ads);
- if (wr < 0) {
- if (!(errno == EAGAIN || errno == EINTR || errno == ENOSPC ||
- errno == ENOBUFS || errno == ENOMEM)) {
- adns__tcp_broken(ads,"write",strerror(errno));
- return;
- }
- wr= 0;
- }
- }
-
- if (wr<2) {
- r= adns__vbuf_append(&ads->tcpsend,length,2-wr); assert(r);
- wr= 0;
- } else {
- wr-= 2;
- }
- if (wr<qu->query_dglen) {
- r= adns__vbuf_append(&ads->tcpsend,qu->query_dgram+wr,qu->query_dglen-wr); assert(r);
- }
-}
-
-static void query_usetcp(adns_query qu, struct timeval now) {
- qu->state= query_tcpw;
- qu->timeout= now;
- timevaladd(&qu->timeout,TCPWAITMS);
- LIST_LINK_TAIL(qu->ads->tcpw,qu);
- adns__querysend_tcp(qu,now);
- adns__tcp_tryconnect(qu->ads,now);
-}
-
-void adns__query_send(adns_query qu, struct timeval now) {
- struct sockaddr_in servaddr;
- int serv, r;
- adns_state ads;
-
- assert(qu->state == query_tosend);
- if ((qu->flags & adns_qf_usevc) || (qu->query_dglen > DNS_MAXUDP)) {
- query_usetcp(qu,now);
- return;
- }
-
- if (qu->retries >= UDPMAXRETRIES) {
- adns__query_fail(qu,adns_s_timeout);
- return;
- }
-
- serv= qu->udpnextserver;
- memset(&servaddr,0,sizeof(servaddr));
-
- ads= qu->ads;
- servaddr.sin_family= AF_INET;
- servaddr.sin_addr= ads->servers[serv].addr;
- servaddr.sin_port= htons(DNS_PORT);
-
- r= sendto(ads->udpsocket,qu->query_dgram,qu->query_dglen,0,
- (const struct sockaddr*)&servaddr,sizeof(servaddr));
- if (r<0 && errno == EMSGSIZE) { qu->retries= 0; query_usetcp(qu,now); return; }
- if (r<0) adns__warn(ads,serv,0,"sendto failed: %s",strerror(errno));
-
- qu->timeout= now;
- timevaladd(&qu->timeout,UDPRETRYMS);
- qu->udpsent |= (1<<serv);
- qu->udpnextserver= (serv+1)%ads->nservers;
- qu->retries++;
- LIST_LINK_TAIL(ads->udpw,qu);
-}
diff --git a/adns-0.6/src/tvarith.h b/adns-0.6/src/tvarith.h
deleted file mode 100644
index 202da1f..0000000
--- a/adns-0.6/src/tvarith.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * tvarith.h
- * - static inline functions for doing arithmetic on timevals
- */
-/*
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef ADNS_TVARITH_H_INCLUDED
-#define ADNS_TVARITH_H_INCLUDED
-
-static inline void timevaladd(struct timeval *tv_io, long ms) {
- struct timeval tmp;
- assert(ms>=0);
- tmp= *tv_io;
- tmp.tv_usec += (ms%1000)*1000;
- tmp.tv_sec += ms/1000;
- if (tmp.tv_usec >= 1000000) { tmp.tv_sec++; tmp.tv_usec -= 1000000; }
- *tv_io= tmp;
-}
-
-#endif
diff --git a/adns-0.6/src/types.c b/adns-0.6/src/types.c
deleted file mode 100644
index 668986f..0000000
--- a/adns-0.6/src/types.c
+++ /dev/null
@@ -1,1034 +0,0 @@
-/*
- * types.c
- * - RR-type-specific code, and the machinery to call it
- */
-/*
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <stdlib.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "internal.h"
-
-#define R_NOMEM return adns_s_nomemory
-#define CSP_ADDSTR(s) do { if (!adns__vbuf_appendstr(vb,(s))) R_NOMEM; } while (0)
-
-/*
- * order of sections:
- *
- * _string (pap)
- * _textdata, _qstring (csp)
- * _str (mf,cs)
- * _intstr (mf,csp,cs)
- * _manyistr (mf,cs)
- * _txt (pa)
- * _inaddr (pa,dip,di)
- * _addr (pa,di,csp,cs)
- * _domain (pap)
- * _host_raw (pa)
- * _hostaddr (pap,pa,dip,di,mfp,mf,csp,cs +pap_findaddrs)
- * _mx_raw (pa,di)
- * _mx (pa,di)
- * _inthostaddr (mf,cs)
- * _ptr (pa)
- * _strpair (mf,cs)
- * _intstrpair (mf,cs)
- * _hinfo (pa)
- * _mailbox (pap +pap_mailbox822)
- * _rp (pa)
- * _soa (pa,mf,cs)
- * _flat (mf)
- *
- * within each section:
- * pap_*
- * pa_*
- * dip_*
- * di_*
- * mfp_*
- * mf_*
- * csp_*
- * cs_*
- */
-
-/*
- * _qstring (pap,csp)
- */
-
-static adns_status pap_qstring(const parseinfo *pai, int *cbyte_io, int max,
- int *len_r, char **str_r) {
- /* Neither len_r nor str_r may be null.
- * End of datagram (overrun) is indicated by returning adns_s_invaliddata;
- */
- const byte *dgram= pai->dgram;
- int l, cbyte;
- char *str;
-
- cbyte= *cbyte_io;
-
- if (cbyte >= max) return adns_s_invaliddata;
- GET_B(cbyte,l);
- if (cbyte+l > max) return adns_s_invaliddata;
-
- str= adns__alloc_interim(pai->qu, l+1);
- if (!str) R_NOMEM;
-
- str[l]= 0;
- memcpy(str,dgram+cbyte,l);
-
- *len_r= l;
- *str_r= str;
- *cbyte_io= cbyte+l;
-
- return adns_s_ok;
-}
-
-static adns_status csp_qstring(vbuf *vb, const char *dp, int len) {
- unsigned char ch;
- char buf[10];
- int cn;
-
- CSP_ADDSTR("\"");
- for (cn=0; cn<len; cn++) {
- ch= *dp++;
- if (ch == '\\') {
- CSP_ADDSTR("\\\\");
- } else if (ch == '"') {
- CSP_ADDSTR("\\\"");
- } else if (ch >= 32 && ch <= 126) {
- if (!adns__vbuf_append(vb,&ch,1)) R_NOMEM;
- } else {
- sprintf(buf,"\\x%02x",ch);
- CSP_ADDSTR(buf);
- }
- }
- CSP_ADDSTR("\"");
-
- return adns_s_ok;
-}
-
-/*
- * _str (mf)
- */
-
-static void mf_str(adns_query qu, void *datap) {
- char **rrp= datap;
-
- adns__makefinal_str(qu,rrp);
-}
-
-/*
- * _intstr (mf)
- */
-
-static void mf_intstr(adns_query qu, void *datap) {
- adns_rr_intstr *rrp= datap;
-
- adns__makefinal_str(qu,&rrp->str);
-}
-
-/*
- * _manyistr (mf)
- */
-
-static void mf_manyistr(adns_query qu, void *datap) {
- adns_rr_intstr **rrp= datap;
- adns_rr_intstr *te, *table;
- void *tablev;
- int tc;
-
- for (tc=0, te= *rrp; te->i >= 0; te++, tc++);
- tablev= *rrp;
- adns__makefinal_block(qu,&tablev,sizeof(*te)*(tc+1));
- *rrp= table= tablev;
- for (te= *rrp; te->i >= 0; te++)
- adns__makefinal_str(qu,&te->str);
-}
-
-/*
- * _txt (pa,cs)
- */
-
-static adns_status pa_txt(const parseinfo *pai, int cbyte, int max, void *datap) {
- adns_rr_intstr **rrp= datap, *table, *te;
- const byte *dgram= pai->dgram;
- int ti, tc, l, startbyte;
- adns_status st;
-
- startbyte= cbyte;
- if (cbyte >= max) return adns_s_invaliddata;
- tc= 0;
- while (cbyte < max) {
- GET_B(cbyte,l);
- cbyte+= l;
- tc++;
- }
- if (cbyte != max || !tc) return adns_s_invaliddata;
-
- table= adns__alloc_interim(pai->qu,sizeof(*table)*(tc+1));
- if (!table) R_NOMEM;
-
- for (cbyte=startbyte, ti=0, te=table; ti<tc; ti++, te++) {
- st= pap_qstring(pai, &cbyte, max, &te->i, &te->str);
- if (st) return st;
- }
- assert(cbyte == max);
-
- te->i= -1;
- te->str= 0;
-
- *rrp= table;
- return adns_s_ok;
-}
-
-static adns_status cs_txt(vbuf *vb, const void *datap) {
- const adns_rr_intstr *const *rrp= datap;
- const adns_rr_intstr *current;
- adns_status st;
- int spc;
-
- for (current= *rrp, spc=0; current->i >= 0; current++, spc=1) {
- if (spc) CSP_ADDSTR(" ");
- st= csp_qstring(vb,current->str,current->i); if (st) return st;
- }
- return adns_s_ok;
-}
-
-/*
- * _hinfo (cs)
- */
-
-static adns_status cs_hinfo(vbuf *vb, const void *datap) {
- const adns_rr_intstrpair *rrp= datap;
- adns_status st;
-
- st= csp_qstring(vb,rrp->array[0].str,rrp->array[0].i); if (st) return st;
- CSP_ADDSTR(" ");
- st= csp_qstring(vb,rrp->array[1].str,rrp->array[1].i); if (st) return st;
- return adns_s_ok;
-}
-
-/*
- * _inaddr (pa,dip,di)
- */
-
-static adns_status pa_inaddr(const parseinfo *pai, int cbyte, int max, void *datap) {
- struct in_addr *storeto= datap;
-
- if (max-cbyte != 4) return adns_s_invaliddata;
- memcpy(storeto, pai->dgram + cbyte, 4);
- return adns_s_ok;
-}
-
-static int search_sortlist(adns_state ads, struct in_addr ad) {
- const struct sortlist *slp;
- int i;
-
- for (i=0, slp=ads->sortlist;
- i<ads->nsortlist && !((ad.s_addr & slp->mask.s_addr) == slp->base.s_addr);
- i++, slp++);
- return i;
-}
-
-static int dip_inaddr(adns_state ads, struct in_addr a, struct in_addr b) {
- int ai, bi;
-
- if (!ads->nsortlist) return 0;
-
- ai= search_sortlist(ads,a);
- bi= search_sortlist(ads,b);
- return bi<ai;
-}
-
-static int di_inaddr(adns_state ads, const void *datap_a, const void *datap_b) {
- const struct in_addr *ap= datap_a, *bp= datap_b;
-
- return dip_inaddr(ads,*ap,*bp);
-}
-
-static adns_status cs_inaddr(vbuf *vb, const void *datap) {
- const struct in_addr *rrp= datap, rr= *rrp;
- const char *ia;
-
- ia= inet_ntoa(rr); assert(ia);
- CSP_ADDSTR(ia);
- return adns_s_ok;
-}
-
-/*
- * _addr (pa,di,csp,cs)
- */
-
-static adns_status pa_addr(const parseinfo *pai, int cbyte, int max, void *datap) {
- adns_rr_addr *storeto= datap;
- const byte *dgram= pai->dgram;
-
- if (max-cbyte != 4) return adns_s_invaliddata;
- storeto->len= sizeof(storeto->addr.inet);
- memset(&storeto->addr,0,sizeof(storeto->addr.inet));
- storeto->addr.inet.sin_family= AF_INET;
- memcpy(&storeto->addr.inet.sin_addr,dgram+cbyte,4);
- return adns_s_ok;
-}
-
-static int di_addr(adns_state ads, const void *datap_a, const void *datap_b) {
- const adns_rr_addr *ap= datap_a, *bp= datap_b;
-
- assert(ap->addr.sa.sa_family == AF_INET);
- return dip_inaddr(ads, ap->addr.inet.sin_addr, bp->addr.inet.sin_addr);
-}
-
-static int div_addr(void *context, const void *datap_a, const void *datap_b) {
- const adns_state ads= context;
-
- return di_addr(ads, datap_a, datap_b);
-}
-
-static adns_status csp_addr(vbuf *vb, const adns_rr_addr *rrp) {
- const char *ia;
- static char buf[30];
-
- switch (rrp->addr.inet.sin_family) {
- case AF_INET:
- CSP_ADDSTR("INET ");
- ia= inet_ntoa(rrp->addr.inet.sin_addr); assert(ia);
- CSP_ADDSTR(ia);
- break;
- default:
- sprintf(buf,"AF=%u",rrp->addr.sa.sa_family);
- CSP_ADDSTR(buf);
- break;
- }
- return adns_s_ok;
-}
-
-static adns_status cs_addr(vbuf *vb, const void *datap) {
- const adns_rr_addr *rrp= datap;
-
- return csp_addr(vb,rrp);
-}
-
-/*
- * _domain (pap,csp,cs)
- * _dom_raw (pa)
- */
-
-static adns_status pap_domain(const parseinfo *pai, int *cbyte_io, int max,
- char **domain_r, parsedomain_flags flags) {
- adns_status st;
- char *dm;
-
- st= adns__parse_domain(pai->qu->ads, pai->serv, pai->qu, &pai->qu->vb, flags,
- pai->dgram,pai->dglen, cbyte_io, max);
- if (st) return st;
- if (!pai->qu->vb.used) return adns_s_invaliddata;
-
- dm= adns__alloc_interim(pai->qu, pai->qu->vb.used+1);
- if (!dm) R_NOMEM;
-
- dm[pai->qu->vb.used]= 0;
- memcpy(dm,pai->qu->vb.buf,pai->qu->vb.used);
-
- *domain_r= dm;
- return adns_s_ok;
-}
-
-static adns_status csp_domain(vbuf *vb, const char *domain) {
- CSP_ADDSTR(domain);
- if (!*domain) CSP_ADDSTR(".");
- return adns_s_ok;
-}
-
-static adns_status cs_domain(vbuf *vb, const void *datap) {
- const char *const *domainp= datap;
- return csp_domain(vb,*domainp);
-}
-
-static adns_status pa_dom_raw(const parseinfo *pai, int cbyte, int max, void *datap) {
- char **rrp= datap;
- adns_status st;
-
- st= pap_domain(pai, &cbyte, max, rrp, pdf_quoteok);
- if (st) return st;
-
- if (cbyte != max) return adns_s_invaliddata;
- return adns_s_ok;
-}
-
-/*
- * _host_raw (pa)
- */
-
-static adns_status pa_host_raw(const parseinfo *pai, int cbyte, int max, void *datap) {
- char **rrp= datap;
- adns_status st;
-
- st= pap_domain(pai, &cbyte, max, rrp,
- pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
- if (st) return st;
-
- if (cbyte != max) return adns_s_invaliddata;
- return adns_s_ok;
-}
-
-/*
- * _hostaddr (pap,pa,dip,di,mfp,mf,csp,cs +icb_hostaddr, pap_findaddrs)
- */
-
-static adns_status pap_findaddrs(const parseinfo *pai, adns_rr_hostaddr *ha,
- int *cbyte_io, int count, int dmstart) {
- int rri, naddrs;
- int type, class, rdlen, rdstart, ownermatched;
- unsigned long ttl;
- adns_status st;
-
- for (rri=0, naddrs=-1; rri<count; rri++) {
- st= adns__findrr_anychk(pai->qu, pai->serv, pai->dgram, pai->dglen, cbyte_io,
- &type, &class, &ttl, &rdlen, &rdstart,
- pai->dgram, pai->dglen, dmstart, &ownermatched);
- if (st) return st;
- if (!ownermatched || class != DNS_CLASS_IN || type != adns_r_a) {
- if (naddrs>0) break; else continue;
- }
- if (naddrs == -1) {
- naddrs= 0;
- }
- if (!adns__vbuf_ensure(&pai->qu->vb, (naddrs+1)*sizeof(adns_rr_addr))) R_NOMEM;
- adns__update_expires(pai->qu,ttl,pai->now);
- st= pa_addr(pai, rdstart,rdstart+rdlen,
- pai->qu->vb.buf + naddrs*sizeof(adns_rr_addr));
- if (st) return st;
- naddrs++;
- }
- if (naddrs >= 0) {
- ha->addrs= adns__alloc_interim(pai->qu, naddrs*sizeof(adns_rr_addr));
- if (!ha->addrs) R_NOMEM;
- memcpy(ha->addrs, pai->qu->vb.buf, naddrs*sizeof(adns_rr_addr));
- ha->naddrs= naddrs;
- ha->astatus= adns_s_ok;
-
- adns__isort(ha->addrs, naddrs, sizeof(adns_rr_addr), pai->qu->vb.buf,
- div_addr, pai->ads);
- }
- return adns_s_ok;
-}
-
-static void icb_hostaddr(adns_query parent, adns_query child) {
- adns_answer *cans= child->answer;
- adns_rr_hostaddr *rrp= child->ctx.info.hostaddr;
- adns_state ads= parent->ads;
- adns_status st;
-
- st= cans->status;
- rrp->astatus= st;
- rrp->naddrs= (st>0 && st<=adns_s_max_tempfail) ? -1 : cans->nrrs;
- rrp->addrs= cans->rrs.addr;
- adns__transfer_interim(child, parent, rrp->addrs, rrp->naddrs*sizeof(adns_rr_addr));
-
- if (parent->children.head) {
- LIST_LINK_TAIL(ads->childw,parent);
- } else {
- adns__query_done(parent);
- }
-}
-
-static adns_status pap_hostaddr(const parseinfo *pai, int *cbyte_io,
- int max, adns_rr_hostaddr *rrp) {
- adns_status st;
- int dmstart, cbyte;
- qcontext ctx;
- int id;
- adns_query nqu;
- adns_queryflags nflags;
-
- dmstart= cbyte= *cbyte_io;
- st= pap_domain(pai, &cbyte, max, &rrp->host,
- pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
- if (st) return st;
- *cbyte_io= cbyte;
-
- rrp->astatus= adns_s_ok;
- rrp->naddrs= -1;
- rrp->addrs= 0;
-
- cbyte= pai->nsstart;
-
- st= pap_findaddrs(pai, rrp, &cbyte, pai->nscount, dmstart);
- if (st) return st;
- if (rrp->naddrs != -1) return adns_s_ok;
-
- st= pap_findaddrs(pai, rrp, &cbyte, pai->arcount, dmstart);
- if (st) return st;
- if (rrp->naddrs != -1) return adns_s_ok;
-
- st= adns__mkquery_frdgram(pai->ads, &pai->qu->vb, &id,
- pai->dgram, pai->dglen, dmstart,
- adns_r_addr, adns_qf_quoteok_query);
- if (st) return st;
-
- ctx.ext= 0;
- ctx.callback= icb_hostaddr;
- ctx.info.hostaddr= rrp;
-
- nflags= adns_qf_quoteok_query;
- if (!(pai->qu->flags & adns_qf_cname_loose)) nflags |= adns_qf_cname_forbid;
-
- st= adns__internal_submit(pai->ads, &nqu, adns__findtype(adns_r_addr),
- &pai->qu->vb, id, nflags, pai->now, &ctx);
- if (st) return st;
-
- nqu->parent= pai->qu;
- LIST_LINK_TAIL_PART(pai->qu->children,nqu,siblings.);
-
- return adns_s_ok;
-}
-
-static adns_status pa_hostaddr(const parseinfo *pai, int cbyte, int max, void *datap) {
- adns_rr_hostaddr *rrp= datap;
- adns_status st;
-
- st= pap_hostaddr(pai, &cbyte, max, rrp);
- if (st) return st;
- if (cbyte != max) return adns_s_invaliddata;
-
- return adns_s_ok;
-}
-
-static int dip_hostaddr(adns_state ads, const adns_rr_hostaddr *ap, const adns_rr_hostaddr *bp) {
- if (ap->astatus != bp->astatus) return ap->astatus;
- if (ap->astatus) return 0;
-
- assert(ap->addrs[0].addr.sa.sa_family == AF_INET);
- assert(bp->addrs[0].addr.sa.sa_family == AF_INET);
- return dip_inaddr(ads,
- ap->addrs[0].addr.inet.sin_addr,
- bp->addrs[0].addr.inet.sin_addr);
-}
-
-static int di_hostaddr(adns_state ads, const void *datap_a, const void *datap_b) {
- const adns_rr_hostaddr *ap= datap_a, *bp= datap_b;
-
- return dip_hostaddr(ads, ap,bp);
-}
-
-static void mfp_hostaddr(adns_query qu, adns_rr_hostaddr *rrp) {
- void *tablev;
-
- adns__makefinal_str(qu,&rrp->host);
- tablev= rrp->addrs;
- adns__makefinal_block(qu, &tablev, rrp->naddrs*sizeof(*rrp->addrs));
- rrp->addrs= tablev;
-}
-
-static void mf_hostaddr(adns_query qu, void *datap) {
- adns_rr_hostaddr *rrp= datap;
-
- mfp_hostaddr(qu,rrp);
-}
-
-static adns_status csp_hostaddr(vbuf *vb, const adns_rr_hostaddr *rrp) {
- const char *errstr;
- adns_status st;
- char buf[20];
- int i;
-
- st= csp_domain(vb,rrp->host); if (st) return st;
-
- CSP_ADDSTR(" ");
- CSP_ADDSTR(adns_errtypeabbrev(rrp->astatus));
-
- sprintf(buf," %d ",rrp->astatus);
- CSP_ADDSTR(buf);
-
- CSP_ADDSTR(adns_errabbrev(rrp->astatus));
- CSP_ADDSTR(" ");
-
- errstr= adns_strerror(rrp->astatus);
- st= csp_qstring(vb,errstr,strlen(errstr)); if (st) return st;
-
- if (rrp->naddrs >= 0) {
- CSP_ADDSTR(" (");
- for (i=0; i<rrp->naddrs; i++) {
- CSP_ADDSTR(" ");
- st= csp_addr(vb,&rrp->addrs[i]);
- }
- CSP_ADDSTR(" )");
- } else {
- CSP_ADDSTR(" ?");
- }
- return adns_s_ok;
-}
-
-static adns_status cs_hostaddr(vbuf *vb, const void *datap) {
- const adns_rr_hostaddr *rrp= datap;
-
- return csp_hostaddr(vb,rrp);
-}
-
-/*
- * _mx_raw (pa,di)
- */
-
-static adns_status pa_mx_raw(const parseinfo *pai, int cbyte, int max, void *datap) {
- const byte *dgram= pai->dgram;
- adns_rr_intstr *rrp= datap;
- adns_status st;
- int pref;
-
- if (cbyte+2 > max) return adns_s_invaliddata;
- GET_W(cbyte,pref);
- rrp->i= pref;
- st= pap_domain(pai, &cbyte, max, &rrp->str,
- pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
- if (st) return st;
-
- if (cbyte != max) return adns_s_invaliddata;
- return adns_s_ok;
-}
-
-static int di_mx_raw(adns_state ads, const void *datap_a, const void *datap_b) {
- const adns_rr_intstr *ap= datap_a, *bp= datap_b;
-
- if (ap->i < bp->i) return 0;
- if (ap->i > bp->i) return 1;
- return 0;
-}
-
-/*
- * _mx (pa,di)
- */
-
-static adns_status pa_mx(const parseinfo *pai, int cbyte, int max, void *datap) {
- const byte *dgram= pai->dgram;
- adns_rr_inthostaddr *rrp= datap;
- adns_status st;
- int pref;
-
- if (cbyte+2 > max) return adns_s_invaliddata;
- GET_W(cbyte,pref);
- rrp->i= pref;
- st= pap_hostaddr(pai, &cbyte, max, &rrp->ha);
- if (st) return st;
-
- if (cbyte != max) return adns_s_invaliddata;
- return adns_s_ok;
-}
-
-static int di_mx(adns_state ads, const void *datap_a, const void *datap_b) {
- const adns_rr_inthostaddr *ap= datap_a, *bp= datap_b;
-
- if (ap->i < bp->i) return 0;
- if (ap->i > bp->i) return 1;
- return dip_hostaddr(ads, &ap->ha, &bp->ha);
-}
-
-/*
- * _inthostaddr (mf,cs)
- */
-
-static void mf_inthostaddr(adns_query qu, void *datap) {
- adns_rr_inthostaddr *rrp= datap;
-
- mfp_hostaddr(qu,&rrp->ha);
-}
-
-static adns_status cs_inthostaddr(vbuf *vb, const void *datap) {
- const adns_rr_inthostaddr *rrp= datap;
- char buf[10];
-
- sprintf(buf,"%u ",rrp->i);
- CSP_ADDSTR(buf);
-
- return csp_hostaddr(vb,&rrp->ha);
-}
-
-/*
- * _inthost (cs)
- */
-
-static adns_status cs_inthost(vbuf *vb, const void *datap) {
- const adns_rr_intstr *rrp= datap;
- char buf[10];
-
- sprintf(buf,"%u ",rrp->i);
- CSP_ADDSTR(buf);
- return csp_domain(vb,rrp->str);
-}
-
-/*
- * _ptr (pa, +icb_ptr)
- */
-
-static void icb_ptr(adns_query parent, adns_query child) {
- adns_answer *cans= child->answer;
- const adns_rr_addr *queried, *found;
- adns_state ads= parent->ads;
- int i;
-
- if (cans->status == adns_s_nxdomain || cans->status == adns_s_nodata) {
- adns__query_fail(parent,adns_s_inconsistent);
- return;
- } else if (cans->status) {
- adns__query_fail(parent,cans->status);
- return;
- }
-
- queried= &parent->ctx.info.ptr_parent_addr;
- for (i=0, found=cans->rrs.addr; i<cans->nrrs; i++, found++) {
- if (queried->len == found->len &&
- !memcmp(&queried->addr,&found->addr,queried->len)) {
- if (!parent->children.head) {
- adns__query_done(parent);
- return;
- } else {
- LIST_LINK_TAIL(ads->childw,parent);
- return;
- }
- }
- }
-
- adns__query_fail(parent,adns_s_inconsistent);
-}
-
-static adns_status pa_ptr(const parseinfo *pai, int dmstart, int max, void *datap) {
- static const char *(expectdomain[])= { DNS_INADDR_ARPA };
-
- char **rrp= datap;
- adns_status st;
- adns_rr_addr *ap;
- findlabel_state fls;
- char *ep;
- byte ipv[4];
- char labbuf[4];
- int cbyte, i, lablen, labstart, l, id;
- adns_query nqu;
- qcontext ctx;
-
- cbyte= dmstart;
- st= pap_domain(pai, &cbyte, max, rrp,
- pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
- if (st) return st;
- if (cbyte != max) return adns_s_invaliddata;
-
- ap= &pai->qu->ctx.info.ptr_parent_addr;
- if (!ap->len) {
- adns__findlabel_start(&fls, pai->ads, -1, pai->qu,
- pai->qu->query_dgram, pai->qu->query_dglen,
- pai->qu->query_dglen, DNS_HDRSIZE, 0);
- for (i=0; i<4; i++) {
- st= adns__findlabel_next(&fls,&lablen,&labstart); assert(!st);
- if (lablen<=0 || lablen>3) return adns_s_querydomainwrong;
- memcpy(labbuf, pai->qu->query_dgram + labstart, lablen); labbuf[lablen]= 0;
- ipv[3-i]= strtoul(labbuf,&ep,10); if (*ep) return adns_s_querydomainwrong;
- if (lablen>1 && pai->qu->query_dgram[labstart]=='0')
- return adns_s_querydomainwrong;
- }
- for (i=0; i<sizeof(expectdomain)/sizeof(*expectdomain); i++) {
- st= adns__findlabel_next(&fls,&lablen,&labstart); assert(!st);
- l= strlen(expectdomain[i]);
- if (lablen != l || memcmp(pai->qu->query_dgram + labstart, expectdomain[i], l))
- return adns_s_querydomainwrong;
- }
- st= adns__findlabel_next(&fls,&lablen,0); assert(!st);
- if (lablen) return adns_s_querydomainwrong;
-
- ap->len= sizeof(struct sockaddr_in);
- memset(&ap->addr,0,sizeof(ap->addr.inet));
- ap->addr.inet.sin_family= AF_INET;
- ap->addr.inet.sin_addr.s_addr=
- htonl((ipv[0]<<24) | (ipv[1]<<16) | (ipv[2]<<8) | (ipv[3]));
- }
-
- st= adns__mkquery_frdgram(pai->ads, &pai->qu->vb, &id,
- pai->dgram, pai->dglen, dmstart,
- adns_r_addr, adns_qf_quoteok_query);
- if (st) return st;
-
- ctx.ext= 0;
- ctx.callback= icb_ptr;
- memset(&ctx.info,0,sizeof(ctx.info));
- st= adns__internal_submit(pai->ads, &nqu, adns__findtype(adns_r_addr),
- &pai->qu->vb, id,
- adns_qf_quoteok_query, pai->now, &ctx);
- if (st) return st;
-
- nqu->parent= pai->qu;
- LIST_LINK_TAIL_PART(pai->qu->children,nqu,siblings.);
- return adns_s_ok;
-}
-
-/*
- * _strpair (mf)
- */
-
-static void mf_strpair(adns_query qu, void *datap) {
- adns_rr_strpair *rrp= datap;
-
- adns__makefinal_str(qu,&rrp->array[0]);
- adns__makefinal_str(qu,&rrp->array[1]);
-}
-
-/*
- * _intstrpair (mf)
- */
-
-static void mf_intstrpair(adns_query qu, void *datap) {
- adns_rr_intstrpair *rrp= datap;
-
- adns__makefinal_str(qu,&rrp->array[0].str);
- adns__makefinal_str(qu,&rrp->array[1].str);
-}
-
-/*
- * _hinfo (pa)
- */
-
-static adns_status pa_hinfo(const parseinfo *pai, int cbyte, int max, void *datap) {
- adns_rr_intstrpair *rrp= datap;
- adns_status st;
- int i;
-
- for (i=0; i<2; i++) {
- st= pap_qstring(pai, &cbyte, max, &rrp->array[i].i, &rrp->array[i].str);
- if (st) return st;
- }
-
- if (cbyte != max) return adns_s_invaliddata;
-
- return adns_s_ok;
-}
-
-/*
- * _mailbox (pap,cs)
- */
-
-static adns_status pap_mailbox822(const parseinfo *pai, int *cbyte_io, int max,
- char **mb_r) {
- int lablen, labstart, i, needquote, c, r, neednorm;
- const unsigned char *p;
- char *str;
- findlabel_state fls;
- adns_status st;
- vbuf *vb;
-
- vb= &pai->qu->vb;
- vb->used= 0;
- adns__findlabel_start(&fls, pai->ads,
- -1, pai->qu,
- pai->dgram, pai->dglen, max,
- *cbyte_io, cbyte_io);
- st= adns__findlabel_next(&fls,&lablen,&labstart);
- if (!lablen) {
- adns__vbuf_appendstr(vb,".");
- goto x_ok;
- }
-
- neednorm= 1;
- for (i=0, needquote=0, p= pai->dgram+labstart; i<lablen; i++) {
- c= *p++;
- if ((c&~128) < 32 || (c&~128) == 127) return adns_s_invaliddata;
- if (c == '.' && !neednorm) neednorm= 1;
- else if (c==' ' || ctype_822special(c)) needquote++;
- else neednorm= 0;
- }
-
- if (needquote || neednorm) {
- r= adns__vbuf_ensure(vb, lablen+needquote+4); if (!r) R_NOMEM;
- adns__vbuf_appendq(vb,"\"",1);
- for (i=0, needquote=0, p= pai->dgram+labstart; i<lablen; i++, p++) {
- c= *p;
- if (c == '"' || c=='\\') adns__vbuf_appendq(vb,"\\",1);
- adns__vbuf_appendq(vb,p,1);
- }
- adns__vbuf_appendq(vb,"\"",1);
- } else {
- r= adns__vbuf_append(vb, pai->dgram+labstart, lablen); if (!r) R_NOMEM;
- }
-
- r= adns__vbuf_appendstr(vb,"@"); if (!r) R_NOMEM;
-
- st= adns__parse_domain_more(&fls,pai->ads, pai->qu,vb,0, pai->dgram);
- if (st) return st;
-
- x_ok:
- str= adns__alloc_interim(pai->qu, vb->used+1); if (!str) R_NOMEM;
- memcpy(str,vb->buf,vb->used);
- str[vb->used]= 0;
- *mb_r= str;
- return adns_s_ok;
-}
-
-static adns_status pap_mailbox(const parseinfo *pai, int *cbyte_io, int max,
- char **mb_r) {
- if (pai->qu->typei->type & adns__qtf_mail822) {
- return pap_mailbox822(pai, cbyte_io, max, mb_r);
- } else {
- return pap_domain(pai, cbyte_io, max, mb_r, pdf_quoteok);
- }
-}
-
-static adns_status csp_mailbox(vbuf *vb, const char *mailbox) {
- return csp_domain(vb,mailbox);
-}
-
-/*
- * _rp (pa,cs)
- */
-
-static adns_status pa_rp(const parseinfo *pai, int cbyte, int max, void *datap) {
- adns_rr_strpair *rrp= datap;
- adns_status st;
-
- st= pap_mailbox(pai, &cbyte, max, &rrp->array[0]);
- if (st) return st;
-
- st= pap_domain(pai, &cbyte, max, &rrp->array[1], pdf_quoteok);
- if (st) return st;
-
- if (cbyte != max) return adns_s_invaliddata;
- return adns_s_ok;
-}
-
-static adns_status cs_rp(vbuf *vb, const void *datap) {
- const adns_rr_strpair *rrp= datap;
- adns_status st;
-
- st= csp_mailbox(vb,rrp->array[0]); if (st) return st;
- CSP_ADDSTR(" ");
- st= csp_domain(vb,rrp->array[1]); if (st) return st;
-
- return adns_s_ok;
-}
-
-/*
- * _soa (pa,mf,cs)
- */
-
-static adns_status pa_soa(const parseinfo *pai, int cbyte, int max, void *datap) {
- adns_rr_soa *rrp= datap;
- const byte *dgram= pai->dgram;
- adns_status st;
- int msw, lsw, i;
-
- st= pap_domain(pai, &cbyte, max, &rrp->mname,
- pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
- if (st) return st;
-
- st= pap_mailbox(pai, &cbyte, max, &rrp->rname);
- if (st) return st;
-
- if (cbyte+20 != max) return adns_s_invaliddata;
-
- for (i=0; i<5; i++) {
- GET_W(cbyte,msw);
- GET_W(cbyte,lsw);
- (&rrp->serial)[i]= (msw<<16) | lsw;
- }
-
- return adns_s_ok;
-}
-
-static void mf_soa(adns_query qu, void *datap) {
- adns_rr_soa *rrp= datap;
-
- adns__makefinal_str(qu,&rrp->mname);
- adns__makefinal_str(qu,&rrp->rname);
-}
-
-static adns_status cs_soa(vbuf *vb, const void *datap) {
- const adns_rr_soa *rrp= datap;
- char buf[20];
- int i;
- adns_status st;
-
- st= csp_domain(vb,rrp->mname); if (st) return st;
- CSP_ADDSTR(" ");
- st= csp_mailbox(vb,rrp->rname); if (st) return st;
-
- for (i=0; i<5; i++) {
- sprintf(buf," %lu",(&rrp->serial)[i]);
- CSP_ADDSTR(buf);
- }
-
- return adns_s_ok;
-}
-
-/*
- * _flat (mf)
- */
-
-static void mf_flat(adns_query qu, void *data) { }
-
-/*
- * Now the table.
- */
-
-#define TYPESZ_M(member) (sizeof(*((adns_answer*)0)->rrs.member))
-
-#define DEEP_MEMB(memb) TYPESZ_M(memb), mf_##memb, cs_##memb
-#define FLAT_MEMB(memb) TYPESZ_M(memb), mf_flat, cs_##memb
-
-#define DEEP_TYPE(code,rrt,fmt,memb,parser,comparer,printer) \
- { adns_r_##code, rrt, fmt, TYPESZ_M(memb), mf_##memb, printer, parser, comparer }
-#define FLAT_TYPE(code,rrt,fmt,memb,parser,comparer,printer) \
- { adns_r_##code, rrt, fmt, TYPESZ_M(memb), mf_flat, printer, parser, comparer }
-
-static const typeinfo typeinfos[] = {
-/* Must be in ascending order of rrtype ! */
-/* mem-mgmt code rrt fmt member parser comparer printer */
-
-FLAT_TYPE(a, "A", 0, inaddr, pa_inaddr, di_inaddr, cs_inaddr ),
-DEEP_TYPE(ns_raw, "NS", "raw", str, pa_host_raw,0, cs_domain ),
-DEEP_TYPE(cname, "CNAME", 0, str, pa_dom_raw, 0, cs_domain ),
-DEEP_TYPE(soa_raw,"SOA", "raw", soa, pa_soa, 0, cs_soa ),
-DEEP_TYPE(ptr_raw,"PTR", "raw", str, pa_host_raw,0, cs_domain ),
-DEEP_TYPE(hinfo, "HINFO", 0, intstrpair, pa_hinfo, 0, cs_hinfo ),
-DEEP_TYPE(mx_raw, "MX", "raw", intstr, pa_mx_raw, di_mx_raw, cs_inthost ),
-DEEP_TYPE(txt, "TXT", 0, manyistr, pa_txt, 0, cs_txt ),
-DEEP_TYPE(rp_raw, "RP", "raw", strpair, pa_rp, 0, cs_rp ),
-
-FLAT_TYPE(addr, "A", "addr", addr, pa_addr, di_addr, cs_addr ),
-DEEP_TYPE(ns, "NS", "+addr", hostaddr, pa_hostaddr,di_hostaddr,cs_hostaddr ),
-DEEP_TYPE(ptr, "PTR","checked",str, pa_ptr, 0, cs_domain ),
-DEEP_TYPE(mx, "MX", "+addr", inthostaddr,pa_mx, di_mx, cs_inthostaddr),
-
-DEEP_TYPE(soa, "SOA","822", soa, pa_soa, 0, cs_soa ),
-DEEP_TYPE(rp, "RP", "822", strpair, pa_rp, 0, cs_rp ),
-};
-
-const typeinfo *adns__findtype(adns_rrtype type) {
- const typeinfo *begin, *end, *mid;
-
- begin= typeinfos; end= typeinfos+(sizeof(typeinfos)/sizeof(typeinfo));
-
- while (begin < end) {
- mid= begin + ((end-begin)>>1);
- if (mid->type == type) return mid;
- if (type > mid->type) begin= mid+1;
- else end= mid;
- }
- return 0;
-}