Index: adns/INSTALL diff -u adns/INSTALL:1.3 adns/INSTALL:1.4 --- adns/INSTALL:1.3 Sun Oct 10 14:16:23 1999 +++ adns/INSTALL Wed Nov 24 16:57:32 1999 @@ -18,6 +18,14 @@ However, if you send me an appropriate patch I'd be willing to make it easy or automatic to disable the ELF shared library arrangements. +The adnsresfilter utility uses `tsearch' from the C library (a la SVID +and X/Open). If your C library doesn't have tsearch you will find +that configure arranges for adnsresfilter not to be built. To rectify +this, install a C library containing tsearch, such as the GNU C +library. It is best if tsearch uses an automatically-balancing tree +algorithm, like the glibc version does. Simple binary trees may +perform badly. + You will probably find that GNU Make is required. @@ -44,3 +52,7 @@ along with userv as the file COPYING; if not, email me at the address above or write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Local variables: +# mode: text +# End: Index: adns/Makefile.in diff -u adns/Makefile.in:1.16 adns/Makefile.in:1.17 --- adns/Makefile.in:1.16 Wed Oct 13 02:26:09 1999 +++ adns/Makefile.in Wed Nov 24 17:17:04 1999 @@ -21,7 +21,7 @@ # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -DISTVERSION= 0.5 +DISTVERSION= 0.6 srcdir= @srcdir@ VPATH= @srcdir@ Index: adns/changelog diff -u adns/changelog:1.58 adns/changelog:1.78 --- adns/changelog:1.58 Wed Oct 13 02:24:43 1999 +++ adns/changelog Wed Nov 24 17:13:07 1999 @@ -1,3 +1,34 @@ +adns (0.6) BETA; urgency=high + + Core library bugfixes: + * Avoid infinite timeouts, causing lockup, when they should be zero ! + * TCP handling revamped (avoids undefined behaviour due to reentrancy). + * Do not fail assertion if _qf_owner, _qf_search, domain ends in `.'. + * Many memory leaks fixed. + + Cool new utility: + * adnsresfilter is like `cat' but converts addresses to names without + delaying the output. Pipe `netstat -n', `tcpdump -ln', etc. into it. + + Test and client program bug and portability fixes: + * Dynamic library building works properly. + * adnshost prints somewhat better messages about some wrong usages. + * Include and in adnshost.h. + * adnslogres: parsing and error checking improved (Tony Finch). + * Regression tests can cope with zero-length reads. + * Regression tests check for memory leaks. + * adnstest copes with empty query type list. + * adnstest uninitialised memory bug fixed. + + General improvements + * Better control of adnshost output and error messages (new -F options). + * New adns_if_logpid option (functionality suggested by Tony Finch). + * New fanftest test program from Tony Finch (ignored by `make install'). + * Reads /etc/resolv-adns.conf if it exists. + * Declare flags parameters as enums again, not ints. + + -- Ian Jackson Wed, 24 Nov 1999 17:13:03 +0000 + adns (0.5) unstable; urgency=high New features: Index: adns/configure diff -u adns/configure:1.8 adns/configure:1.10 --- adns/configure:1.8 Wed Oct 13 02:16:30 1999 +++ adns/configure Wed Nov 24 16:57:32 1999 @@ -1040,14 +1040,71 @@ +PROGS_IF_TSEARCH=adnsresfilter + +echo $ac_n "checking for tsearch""... $ac_c" 1>&6 +echo "configure:1047: checking for tsearch" >&5 +if eval "test \"`echo '$''{'ac_cv_func_tsearch'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char tsearch(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_tsearch) || defined (__stub___tsearch) +choke me +#else +tsearch(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1075: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_tsearch=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_tsearch=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'tsearch`\" = yes"; then + echo "$ac_t""yes" 1>&6 + + PROGS_HAVE_TSEARCH=$PROGS_IF_TSEARCH + +else + echo "$ac_t""no" 1>&6 + + PROGS_HAVE_TSEARCH=''; + echo "configure: warning: tsearch missing - not building client program(s) $PROGS_IF_TSEARCH" 1>&2 + +fi + + echo $ac_n "checking for INADDR_LOOPBACK""... $ac_c" 1>&6 -echo "configure:1045: checking for INADDR_LOOPBACK" >&5 +echo "configure:1102: checking for INADDR_LOOPBACK" >&5 if eval "test \"`echo '$''{'adns_cv_decl_inaddrloopback'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -1060,7 +1117,7 @@ ; return 0; } EOF -if { (eval echo configure:1064: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1121: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* adns_cv_decl_inaddrloopback=yes else @@ -1078,17 +1135,17 @@ echo "$ac_t""not in standard headers, urgh..." 1>&6 ac_safe=`echo "rpc/types.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for rpc/types.h""... $ac_c" 1>&6 -echo "configure:1082: checking for rpc/types.h" >&5 +echo "configure:1139: checking for rpc/types.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1092: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1149: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -1121,12 +1178,12 @@ echo $ac_n "checking for inet_aton""... $ac_c" 1>&6 -echo "configure:1125: checking for inet_aton" >&5 +echo "configure:1182: checking for inet_aton" >&5 if eval "test \"`echo '$''{'ac_cv_func_inet_aton'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1210: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_inet_aton=yes" else @@ -1168,7 +1225,7 @@ echo "$ac_t""no" 1>&6 echo $ac_n "checking for inet_aton in -lresolv""... $ac_c" 1>&6 -echo "configure:1172: checking for inet_aton in -lresolv" >&5 +echo "configure:1229: checking for inet_aton in -lresolv" >&5 ac_lib_var=`echo resolv'_'inet_aton | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1176,7 +1233,7 @@ ac_save_LIBS="$LIBS" LIBS="-lresolv $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1248: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1221,20 +1278,20 @@ echo $ac_n "checking __attribute__((,,))""... $ac_c" 1>&6 -echo "configure:1225: checking __attribute__((,,))" >&5 +echo "configure:1282: checking __attribute__((,,))" >&5 if eval "test \"`echo '$''{'adns_cv_c_attribute_supported'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1295: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* adns_cv_c_attribute_supported=yes else @@ -1256,20 +1313,20 @@ echo $ac_n "checking __attribute__((noreturn))""... $ac_c" 1>&6 -echo "configure:1260: checking __attribute__((noreturn))" >&5 +echo "configure:1317: checking __attribute__((noreturn))" >&5 if eval "test \"`echo '$''{'adns_cv_c_attribute_noreturn'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1330: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* adns_cv_c_attribute_noreturn=yes else @@ -1296,20 +1353,20 @@ echo $ac_n "checking __attribute__((const))""... $ac_c" 1>&6 -echo "configure:1300: checking __attribute__((const))" >&5 +echo "configure:1357: checking __attribute__((const))" >&5 if eval "test \"`echo '$''{'adns_cv_c_attribute_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1370: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* adns_cv_c_attribute_const=yes else @@ -1336,20 +1393,20 @@ echo $ac_n "checking __attribute__((format...))""... $ac_c" 1>&6 -echo "configure:1340: checking __attribute__((format...))" >&5 +echo "configure:1397: checking __attribute__((format...))" >&5 if eval "test \"`echo '$''{'adns_cv_attribute_format'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1410: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* adns_cv_attribute_format=yes else @@ -1398,15 +1455,15 @@ -SHLIBCC='$(CC) $(CFLAGS) -fpic' -MKSHLIB_1='$(CC) $(LDFLAGS) -shared -Wxl,soname=$(SONAME) -o' -MKSHLIB_2='' -MKSHLIB_3='-lc' - SHLIBFORLINK='libadns.so' SHLIBSONAME='$(SHLIBFORLINK).$(MAJOR)' SHLIBFILE='$(SHLIBSONAME).$(MINOR)' +SHLIBCC='$(CC) $(CFLAGS) -fpic' +MKSHLIB_1='$(CC) $(LDFLAGS) -shared -Wl,-soname=$(SHLIBSONAME) -o' +MKSHLIB_2='' +MKSHLIB_3='-lc' + trap '' 1 2 15 cat > confcache <<\EOF # This file is a shell script that caches the results of configure @@ -1542,6 +1599,7 @@ s%@CC@%$CC%g s%@CPP@%$CPP%g s%@RANLIB@%$RANLIB%g +s%@PROGS_HAVE_TSEARCH@%$PROGS_HAVE_TSEARCH%g s%@WARNS@%$WARNS%g s%@SHLIBCC@%$SHLIBCC%g s%@MKSHLIB_1@%$MKSHLIB_1%g Index: adns/configure.in diff -u adns/configure.in:1.9 adns/configure.in:1.11 --- adns/configure.in:1.9 Wed Oct 13 02:16:30 1999 +++ adns/configure.in Wed Nov 24 16:57:32 1999 @@ -31,6 +31,15 @@ ADNS_C_GETFUNC(socket,socket) ADNS_C_GETFUNC(inet_ntoa,nsl) +PROGS_IF_TSEARCH=adnsresfilter +AC_SUBST(PROGS_HAVE_TSEARCH) +AC_CHECK_FUNC(tsearch,[ + PROGS_HAVE_TSEARCH=$PROGS_IF_TSEARCH +],[ + PROGS_HAVE_TSEARCH=''; + AC_MSG_WARN([tsearch missing - not building client program(s) $PROGS_IF_TSEARCH]) +]) + AC_MSG_CHECKING(for INADDR_LOOPBACK) AC_CACHE_VAL(adns_cv_decl_inaddrloopback,[ AC_TRY_COMPILE([ @@ -77,14 +86,14 @@ AC_SUBST(SHLIBFILE) AC_SUBST(SHLIBSONAME) -SHLIBCC='$(CC) $(CFLAGS) -fpic' -MKSHLIB_1='$(CC) $(LDFLAGS) -shared -Wxl,soname=$(SONAME) -o' -MKSHLIB_2='' -MKSHLIB_3='-lc' - SHLIBFORLINK='libadns.so' SHLIBSONAME='$(SHLIBFORLINK).$(MAJOR)' SHLIBFILE='$(SHLIBSONAME).$(MINOR)' + +SHLIBCC='$(CC) $(CFLAGS) -fpic' +MKSHLIB_1='$(CC) $(LDFLAGS) -shared -Wl,-soname=$(SHLIBSONAME) -o' +MKSHLIB_2='' +MKSHLIB_3='-lc' AC_OUTPUT( settings.make Makefile Index: adns/client/.cvsignore diff -u adns/client/.cvsignore:1.5 adns/client/.cvsignore:1.7 --- adns/client/.cvsignore:1.5 Sun Aug 15 18:23:14 1999 +++ adns/client/.cvsignore Wed Nov 3 02:25:25 1999 @@ -5,3 +5,7 @@ adnslogres_s adnshost adnshost_s +adnsresfilter +adnsresfilter_s +fanftest +fanftest_s Index: adns/client/Makefile.in diff -u adns/client/Makefile.in:1.14 adns/client/Makefile.in:1.20 --- adns/client/Makefile.in:1.14 Wed Oct 13 02:23:38 1999 +++ adns/client/Makefile.in Wed Nov 24 16:57:32 1999 @@ -24,17 +24,26 @@ srcdir= @srcdir@ VPATH= @srcdir@ -PROGRAMS= adnstest adnslogres adnshost +PROGS_SYSDEP= @PROGS_HAVE_TSEARCH@ + +PROGRAMS= adnstest adnslogres adnshost $(PROGS_SYSDEP) +PROGRAMS_LOCAL= fanftest +PROGRAMS_ALL= $(PROGRAMS) $(PROGRAMS_LOCAL) + TARG_INSTALL= $(PROGRAMS) -TARG_LOCAL= $(addsuffix _s, $(PROGRAMS)) +TARG_LOCAL= $(addsuffix _s, $(PROGRAMS_ALL)) TARGETS= $(TARG_LOCAL) $(TARG_INSTALL) include $(srcdir)/../settings.make DIRCFLAGS= -I$(srcdir)/../src +TARG_OBJS= $(addsuffix .o, $(PROGRAMS_ALL)) ADH_OBJS= adh-main.o adh-opts.o adh-query.o +ALL_OBJS= $(ADH_OBJS) $(TARG_OBJS) + +ADNSDIR= $(srcdir)/../src/ -STATIC_LIB= $(srcdir)/../src/libadns.a +STATIC_LIB= $(ADNSDIR)/libadns.a DYNAMIC_DEP= $(srcdir)/../dynamic/$(SHLIBFILE) DYNAMIC_LINK= -L$(srcdir)/../dynamic -ladns @@ -47,16 +56,19 @@ uninstall: for f in $(TARGETS); do rm -f $(bin_dir)/$$f; done -$(ADH_OBJS): adnshost.h - adnshost: $(ADH_OBJS) $(DYNAMIC_DEP) $(CC) $(LDFLAGS) $(ADH_OBJS) $(DYNAMIC_LINK) -o $@ $(LDLIBS) adnshost_s: $(ADH_OBJS) $(STATIC_LIB) $(CC) $(LDFLAGS) $(ADH_OBJS) $(STATIC_LIB) -o $@ $(LDLIBS) +$(ADH_OBJS): adnshost.h +$(ALL_OBJS): $(ADNSDIR)/adns.h $(ADNSDIR)/config.h +adnsresfilter.o: $(ADNSDIR)/tvarith.h + %: %.o $(DYNAMIC_DEP) $(CC) $(LDFLAGS) $< $(DYNAMIC_LINK) -o $@ $(LDLIBS) %_s: %.o $(STATIC_LIB) $(CC) $(LDFLAGS) $< $(STATIC_LIB) -o $@ $(LDLIBS) + Index: adns/client/adh-opts.c diff -u adns/client/adh-opts.c:1.8 adns/client/adh-opts.c:1.10 --- adns/client/adh-opts.c:1.8 Wed Oct 13 01:57:36 1999 +++ adns/client/adh-opts.c Fri Oct 15 18:55:45 1999 @@ -32,7 +32,7 @@ int ov_verbose= 0; adns_rrtype ov_type= adns_r_none; int ov_search=0, ov_qc_query=0, ov_qc_anshost=0, ov_qc_cname=1; -int ov_tcp=0, ov_cname=0; +int ov_tcp=0, ov_cname=0, ov_format=fmt_default; char *ov_id= 0; struct perqueryflags_remember ov_pqfr = { 1,1,1, tm_none }; @@ -44,6 +44,14 @@ "f", "pipe", &ov_pipe, 1 }, { ot_flag, "Allow answers to be reordered", "a", "asynch", &ov_asynch, 1 }, + + { ot_desconly, "answer/error output format and destination (see below):" }, + { ot_value, "Answers to stdout, errors as messages to stderr (default)", + "Fs", "fmt-simple", &ov_format, fmt_simple }, + { ot_value, "Answers and errors both to stdout in parseable format", + "Fi", "fmt-inline", &ov_format, fmt_inline }, + { ot_value, "Fully-parseable output format (default for --asynch)", + "Fa", "fmt-asynch", &ov_format, fmt_asynch }, { ot_desconly, "global verbosity level:" }, { ot_value, "Do not print anything to stderr", @@ -216,11 +224,12 @@ "or if the domain refers to a CNAME and --show-cname is on\n" " [] [] CNAME \n" " [] [] \n" - "When a query fails you get a line like this (broken here for readability):\n" + "When a query fails you get an error message to stderr (with --fmt-simple).\n" + "Specify --fmt-inline for lines like this (broken here for readability):\n" " ; failed \\\n" " [] [] [] \"\"\n" - "\n" - "If you use --asynch each answer (success or failure) is preceded by a line\n" + "If you use --fmt-asynch, which is the default for --asynch,\n" + "each answer (success or failure) is preceded by a line\n" " \\\n" " [] [] [] \"\"\n" "where is the number of RRs that follow and will be `$' or\n" @@ -285,12 +294,14 @@ const char *prefix, comparer_type *comparer) { const struct optioninfo *oip; + const char *opt; + opt= *optp; oip= find1(optp,perquery_options,comparer); if (oip) return oip; oip= find1(optp,global_options,comparer); - if (!oip) usageerr("unknown option %s%s",prefix,*optp); - if (ads) usageerr("global option %s%s specified after query domain(s)",prefix,*optp); + if (!oip) usageerr("unknown option %s%s",prefix,opt); + if (ads) usageerr("global option %s%s specified after query domain(s)",prefix,opt); return oip; } Index: adns/client/adh-query.c diff -u adns/client/adh-query.c:1.8 adns/client/adh-query.c:1.10 --- adns/client/adh-query.c:1.8 Wed Oct 13 01:57:36 1999 +++ adns/client/adh-query.c Fri Oct 15 18:55:45 1999 @@ -45,6 +45,9 @@ ov_verbose, 0); if (r) sysfail("adns_init",r); + + if (ov_format == fmt_default) + ov_format= ov_asynch ? fmt_asynch : fmt_simple; } static void prep_query(struct query_node **qun_r, int *quflags_r) { @@ -67,7 +70,7 @@ *quflags_r= (ov_search ? adns_qf_search : 0) | (ov_tcp ? adns_qf_usevc : 0) | - (ov_pqfr.show_owner ? adns_qf_owner : 0) | + ((ov_pqfr.show_owner || ov_format == fmt_simple) ? adns_qf_owner : 0) | (ov_qc_query ? adns_qf_quoteok_query : 0) | (ov_qc_anshost ? adns_qf_quoteok_anshost : 0) | (ov_qc_cname ? 0 : adns_qf_quoteok_cname) | @@ -147,7 +150,7 @@ print_ttl(qun,answer); } -static void print_status(adns_status st, struct query_node *qun, adns_answer *answer) { +static void check_status(adns_status st) { static const adns_status statuspoints[]= { adns_s_ok, adns_s_max_localfail, adns_s_max_remotefail, adns_s_max_tempfail, @@ -155,16 +158,19 @@ }; const adns_status *spp; - const char *statustypeabbrev, *statusabbrev, *statusstring; int minrcode; - statustypeabbrev= adns_errtypeabbrev(st); for (minrcode=0, spp=statuspoints; spp < statuspoints + (sizeof(statuspoints)/sizeof(statuspoints[0])); spp++) if (st > *spp) minrcode++; if (rcode < minrcode) rcode= minrcode; +} +static void print_status(adns_status st, struct query_node *qun, adns_answer *answer) { + const char *statustypeabbrev, *statusabbrev, *statusstring; + + statustypeabbrev= adns_errtypeabbrev(st); statusabbrev= adns_errabbrev(st); statusstring= adns_strerror(st); assert(!strchr(statusstring,'"')); @@ -177,6 +183,32 @@ if (printf("\"%s\"\n", statusstring) == EOF) outerr(); } +static void print_dnsfail(adns_status st, struct query_node *qun, adns_answer *answer) { + int r; + const char *typename, *statusstring; + adns_status ist; + + if (ov_format == fmt_inline) { + if (fputs("; failed ",stdout) == EOF) outerr(); + print_status(st,qun,answer); + return; + } + assert(ov_format == fmt_simple); + if (st == adns_s_nxdomain) { + r= fprintf(stderr,"%s does not exist\n", answer->owner); + } else { + ist= adns_rr_info(answer->type, &typename, 0,0,0,0); + if (st == adns_s_nodata) { + r= fprintf(stderr,"%s has no %s record\n", answer->owner, typename); + } else { + statusstring= adns_strerror(st); + r= fprintf(stderr,"Error during DNS %s lookup for %s: %s\n", + typename, answer->owner, statusstring); + } + } + if (r == EOF) sysfail("write error message to stderr",errno); +} + void query_done(struct query_node *qun, adns_answer *answer) { adns_status st, ist; int rrn, nrrs; @@ -185,20 +217,23 @@ st= answer->status; nrrs= answer->nrrs; - if (ov_asynch) { + if (ov_format == fmt_asynch) { + check_status(st); if (printf("%s %d ", qun->id, nrrs) == EOF) outerr(); print_status(st,qun,answer); } else { - if (st) { - if (fputs("; failed ",stdout) == EOF) outerr(); - print_status(st,qun,answer); - } else if (qun->pqfr.show_cname && answer->cname) { + if (qun->pqfr.show_cname && answer->cname) { print_owner_ttl(qun,answer); - if (printf("CNAME %s\n",answer->cname) == EOF) outerr(); + if (qun->pqfr.show_type) print_withspace("CNAME"); + if (printf("%s\n", answer->cname) == EOF) outerr(); + } + if (st) { + check_status(st); + print_dnsfail(st,qun,answer); } } if (qun->pqfr.show_owner) { - realowner= answer->cname ? answer->cname : answer->owner;; + realowner= answer->cname ? answer->cname : answer->owner; assert(realowner); } else { realowner= 0; Index: adns/client/adnshost.h diff -u adns/client/adnshost.h:1.6 adns/client/adnshost.h:1.9 --- adns/client/adnshost.h:1.6 Wed Oct 13 01:57:36 1999 +++ adns/client/adnshost.h Tue Nov 2 22:22:43 1999 @@ -28,6 +28,7 @@ #ifndef ADNSHOST_H_INCLUDED #define ADNSHOST_H_INCLUDED +#include #include #include #include @@ -36,6 +37,7 @@ #include #include +#include #include #include #include @@ -62,6 +64,7 @@ }; enum ttlmode { tm_none, tm_rel, tm_abs }; +enum outputformat { fmt_default, fmt_simple, fmt_inline, fmt_asynch }; struct perqueryflags_remember { int show_owner, show_type, show_cname; @@ -72,7 +75,7 @@ extern int ov_verbose; extern adns_rrtype ov_type; extern int ov_search, ov_qc_query, ov_qc_anshost, ov_qc_cname; -extern int ov_tcp, ov_cname; +extern int ov_tcp, ov_cname, ov_format; extern char *ov_id; extern struct perqueryflags_remember ov_pqfr; Index: adns/client/adnslogres.c diff -u adns/client/adnslogres.c:1.5 adns/client/adnslogres.c:1.7 --- adns/client/adnslogres.c:1.5 Tue Oct 12 23:56:16 1999 +++ adns/client/adnslogres.c Fri Oct 15 17:46:14 1999 @@ -30,7 +30,7 @@ */ static const char * const cvsid = - "$Id: adnslogres.c,v 1.5 1999/10/12 22:56:16 ian Exp $"; + "$Id: adnslogres.c,v 1.7 1999/10/15 16:46:14 ian Exp $"; #include #include @@ -56,9 +56,12 @@ static const char *progname; -static void aargh(const char *msg) { - fprintf(stderr, "%s: %s: %s (%d)\n", progname, msg, - strerror(errno) ? strerror(errno) : "Unknown error", errno); +#define msg(fmt, args...) fprintf(stderr, "%s: " fmt "\n", progname, ##args) + +static void aargh(const char *cause) { + const char *why = strerror(errno); + if (!why) why = "Unknown error"; + msg("%s: %s (%d)", cause, why, errno); exit(1); } @@ -78,13 +81,15 @@ *addr= *rest= NULL; return buf; } - for (i= 1; i < 5; i ++) { - ptrs[i]= strchr(ptrs[i-1], (i == 4) ? ' ' : '.'); - if (!ptrs[i] || ptrs[i]-ptrs[i-1] > 3) { - ptrs[0]++; + for (i= 1; i < 5; i++) { + ptrs[i]= ptrs[i-1]; + while (isdigit(*ptrs[i]++)); + if ((i == 4 && !isspace(ptrs[i][-1])) || + (i != 4 && ptrs[i][-1] != '.') || + (ptrs[i]-ptrs[i-1] > 4)) { + ptrs[0]= ptrs[i]-1; goto retry; - } else - ptrs[i]++; + } } sprintf(buf, "%.*s.%.*s.%.*s.%.*s.in-addr.arpa.", ptrs[4]-ptrs[3]-1, ptrs[3], @@ -96,12 +101,12 @@ return buf; } -static void printline(char *start, char *addr, char *rest, char *domain) { +static void printline(FILE *outf, char *start, char *addr, char *rest, char *domain) { if (domain) - printf("%.*s%s%s", addr - start, start, domain, rest); + fprintf(outf, "%.*s%s%s", addr - start, start, domain, rest); else - fputs(start, stdout); - if (ferror(stdout)) aargh("write output"); + fputs(start, outf); + if (ferror(outf)) aargh("write output"); } typedef struct logline { @@ -110,33 +115,33 @@ adns_query query; } logline; -static logline *readline(adns_state adns, int opts) { +static logline *readline(FILE *inf, adns_state adns, int opts) { static char buf[MAXLINE]; char *str; logline *line; - if (fgets(buf, MAXLINE, stdin)) { + if (fgets(buf, MAXLINE, inf)) { str= malloc(sizeof(*line) + strlen(buf) + 1); if (!str) aargh("malloc"); line= (logline*)str; line->next= NULL; line->start= str+sizeof(logline); strcpy(line->start, buf); - str = ipaddr2domain(line->start, &line->addr, &line->rest); + str= ipaddr2domain(line->start, &line->addr, &line->rest); if (opts & OPT_DEBUG) - fprintf(stderr, "%s: adns_submit %s\n", progname, str); + msg("submitting %.*s -> %s", line->rest-line->addr, line->addr, str); if (adns_submit(adns, str, adns_r_ptr, adns_qf_quoteok_cname|adns_qf_cname_loose, NULL, &line->query)) aargh("adns_submit"); return line; } - if (!feof(stdin)) + if (!feof(inf)) aargh("fgets"); return NULL; } -static void proclog(int opts) { +static void proclog(FILE *inf, FILE *outf, int opts) { int eof, err, len; adns_state adns; adns_answer *answer; @@ -144,9 +149,12 @@ errno= adns_init(&adns, (opts & OPT_DEBUG) ? adns_if_debug : 0, 0); if (errno) aargh("adns_init"); - head= tail= readline(adns, opts); + head= tail= readline(inf, adns, opts); len= 1; eof= 0; while (head) { + if (opts & OPT_DEBUG) + msg("%d in queue; checking %.*s", len, + head->rest-head->addr, head->addr); if (eof || len > MAXPENDING) if (opts & OPT_POLL) err= adns_wait_poll(adns, &head->query, &answer, NULL); @@ -155,22 +163,22 @@ else err= adns_check(adns, &head->query, &answer, NULL); if (err != EAGAIN) { - printline(head->start, head->addr, head->rest, - answer->status == adns_s_ok ? *answer->rrs.str : NULL); - line= head; head= head->next; - free(line); free(answer); - len--; + printline(outf, head->start, head->addr, head->rest, + answer->status == adns_s_ok ? *answer->rrs.str : NULL); + line= head; head= head->next; + free(line); free(answer); + len--; } if (!eof) { - line= readline(adns, opts); + line= readline(inf, adns, opts); if (!line) eof= 1; else { if (!head) - head = line; + head= line; else - tail->next = line; - tail = line; + tail->next= line; + tail= line; len++; } } @@ -178,30 +186,54 @@ adns_finish(adns); } +static void usage(void) { + fprintf(stderr, "usage: %s [-d] [-p] [logfile]\n", progname); + exit(1); +} + int main(int argc, char *argv[]) { int c, opts; + FILE *inf; - progname= *argv; + progname= strrchr(*argv, '/'); + if (progname) + progname++; + else + progname= *argv; opts= 0; - while ((c= getopt(argc, argv, "dp")) != -1) { + while ((c= getopt(argc, argv, "dp")) != -1) switch (c) { case 'd': - opts |= OPT_DEBUG; + opts|= OPT_DEBUG; break; case 'p': - opts |= OPT_POLL; + opts|= OPT_POLL; break; default: - fprintf(stderr, "usage: %s [-d] < logfile\n", progname); - exit(1); + usage(); } - argc-= optind; - argv+= optind; - } + + argc-= optind; + argv+= optind; + + inf= NULL; + if (argc == 0) + inf= stdin; + else if (argc == 1) + inf= fopen(*argv, "r"); + else + usage(); + + if (!inf) + aargh("couldn't open input"); + + proclog(inf, stdout, opts); - proclog(opts); + if (fclose(inf)) + aargh("fclose input"); + if (fclose(stdout)) + aargh("fclose output"); - if (fclose(stdout)) aargh("finish writing output"); return 0; } Index: adns/client/adnsresfilter.c diff -u /dev/null adns/client/adnsresfilter.c:1.6 --- /dev/null Wed Nov 24 17:20:58 1999 +++ adns/client/adnsresfilter.c Wed Nov 24 17:10:56 1999 @@ -0,0 +1,454 @@ +/* + * adnsresfilter.c + * - filter which does resolving, not part of the library + */ +/* + * This file is + * Copyright (C) 1999 Ian Jackson + * + * It is part of adns, which is + * Copyright (C) 1997-1999 Ian Jackson + * Copyright (C) 1999 Tony Finch + * + * 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 +#include +#include +#include +#include +#include +#include + +#include + +#include "adns.h" +#include "config.h" +#include "dlist.h" +#include "tvarith.h" + +struct outqueuenode { + struct outqueuenode *next, *back; + void *buffer; + char *textp; + int textlen; + struct timeval printbefore; + struct treething *addr; +}; + +static int bracket, forever, address; +static unsigned long timeout=100; +static adns_rrtype rrt= adns_r_ptr; + +static int outblocked, inputeof; +static struct { struct outqueuenode *head, *tail; } outqueue; +static int peroutqueuenode, outqueuelen; + +static struct sockaddr_in sa; +static adns_state ads; + +static char addrtextbuf[14]; +static int cbyte, inbyte, inbuf; +static unsigned char bytes[4]; +static struct timeval printbefore; + +struct treething { + unsigned char bytes[4]; + adns_query qu; + adns_answer *ans; +}; + +static struct treething *newthing; +static void *treeroot; + +static int nonblock(int fd, int isnonblock) { + int r; + + r= fcntl(fd,F_GETFL); + if (r==-1) return -1; + r= fcntl(fd,F_SETFL, isnonblock ? r|O_NONBLOCK : r&~O_NONBLOCK); + if (r==-1) return -1; + return 0; +} + +static void quit(int exitstatus) NONRETURNING; +static void quit(int exitstatus) { + nonblock(0,0); + nonblock(1,0); + exit(exitstatus); +} + +static void sysfail(const char *what) NONRETURNING; +static void sysfail(const char *what) { + fprintf(stderr,"adnsresfilter: system call failed: %s: %s\n",what,strerror(errno)); + quit(2); +} + +static void *xmalloc(size_t sz) { + void *r; + r= malloc(sz); if (r) return r; + sysfail("malloc"); +} + +static void outputerr(void) NONRETURNING; +static void outputerr(void) { sysfail("write to stdout"); } + +static void usage(void) { + if (printf("usage: adnsresfilter []\n" + " adnsresfilter -h|--help\n" + "options: -t|--timeout \n" + " -w|--wait (always wait for queries to time out or fail)\n" + " -b|--brackets (require [...] around IP addresses)\n" + " -a|--address (always include [address] in output)\n" + " -u|--unchecked (do not forward map for checking)\n" + "Timeout is the maximum amount to delay any particular bit of output for.\n" + "Lookups will go on in the background. Default timeout = 100 (ms).\n") + == EOF) outputerr(); +} + +static void usageerr(const char *why) NONRETURNING; +static void usageerr(const char *why) { + fprintf(stderr,"adnsresfilter: bad usage: %s\n",why); + usage(); + quit(1); +} + +static void adnsfail(const char *what, int e) NONRETURNING; +static void adnsfail(const char *what, int e) { + fprintf(stderr,"adnsresfilter: adns call failed: %s: %s\n",what,strerror(e)); + quit(2); +} + +static void settimeout(const char *arg) { + char *ep; + timeout= strtoul(arg,&ep,0); + if (*ep) usageerr("invalid timeout"); +} + +static void parseargs(const char *const *argv) { + const char *arg; + int c; + + while ((arg= *++argv)) { + if (arg[0] != '-') usageerr("no non-option arguments are allowed"); + if (arg[1] == '-') { + if (!strcmp(arg,"--brackets")) { + bracket= 1; + } else if (!strcmp(arg,"--unchecked")) { + rrt= adns_r_ptr_raw; + } else if (!strcmp(arg,"--wait")) { + forever= 1; + } else if (!strcmp(arg,"--address")) { + address= 1; + } else if (!strcmp(arg,"--help")) { + usage(); quit(0); + } else if (!strcmp(arg,"--timeout")) { + if (!(arg= *++argv)) usageerr("--timeout needs a value"); + settimeout(arg); + forever= 0; + } else { + usageerr("unknown long option"); + } + } else { + while ((c= *++arg)) { + switch (c) { + case 'b': + bracket= 1; + break; + case 'u': + rrt= adns_r_ptr_raw; + break; + case 'w': + forever= 1; + break; + case 'a': + address= 1; + break; + case 'h': + usage(); + quit(0); + case 't': + if (*++arg) settimeout(arg); + else if ((arg= *++argv)) settimeout(arg); + else usageerr("-t needs a value"); + forever= 0; + arg= "\0"; + break; + default: + usageerr("unknown short option"); + } + } + } + } +} + +static void queueoutchar(int c) { + struct outqueuenode *entry; + + entry= outqueue.tail; + if (!entry || entry->addr || entry->textlen >= peroutqueuenode) { + peroutqueuenode= !peroutqueuenode || !entry || entry->addr ? 128 : + peroutqueuenode >= 1024 ? 4096 : peroutqueuenode<<2; + entry= xmalloc(sizeof(*entry)); + entry->buffer= xmalloc(peroutqueuenode); + entry->textp= entry->buffer; + entry->textlen= 0; + entry->addr= 0; + LIST_LINK_TAIL(outqueue,entry); + outqueuelen++; + } + entry->textp[entry->textlen++]= c; +} + +static void queueoutstr(const char *str, int len) { + while (len-- > 0) queueoutchar(*str++); +} + +static void writestdout(struct outqueuenode *entry) { + int r; + + while (entry->textlen) { + r= write(1, entry->textp, entry->textlen); + if (r < 0) { + if (errno == EINTR) continue; + if (errno == EAGAIN) { outblocked= 1; break; } + sysfail("write stdout"); + } + assert(r <= entry->textlen); + entry->textp += r; + entry->textlen -= r; + } + if (!entry->textlen) { + LIST_UNLINK(outqueue,entry); + free(entry->buffer); + free(entry); + outqueuelen--; + } +} + +static void replacetextwithname(struct outqueuenode *entry) { + char *name, *newbuf; + int namelen, newlen; + + name= entry->addr->ans->rrs.str[0]; + namelen= strlen(name); + if (!address) { + free(entry->buffer); + entry->buffer= 0; + entry->textp= name; + entry->textlen= namelen; + } else { + newlen= entry->textlen + namelen + (bracket ? 0 : 2); + newbuf= xmalloc(newlen + 1); + sprintf(newbuf, bracket ? "%s%.*s" : "%s[%.*s]", name, entry->textlen, entry->textp); + free(entry->buffer); + entry->buffer= entry->textp= newbuf; + entry->textlen= newlen; + } +} + +static void checkadnsqueries(void) { + adns_query qu; + adns_answer *ans; + void *context; + struct treething *foundthing; + int r; + + for (;;) { + qu= 0; context= 0; ans= 0; + r= adns_check(ads,&qu,&ans,&context); + if (r == ESRCH || r == EAGAIN) break; + assert(!r); + foundthing= context; + foundthing->ans= ans; + foundthing->qu= 0; + } +} + +static void restartbuf(void) { + if (inbuf>0) queueoutstr(addrtextbuf,inbuf); + inbuf= 0; +} + +static int comparer(const void *a, const void *b) { + return memcmp(a,b,4); +} + +static void procaddr(void) { + struct treething *foundthing; + void **searchfound; + struct outqueuenode *entry; + int r; + + if (!newthing) { + newthing= xmalloc(sizeof(struct treething)); + newthing->qu= 0; + newthing->ans= 0; + } + + memcpy(newthing->bytes,bytes,4); + searchfound= tsearch(newthing,&treeroot,comparer); + if (!searchfound) sysfail("tsearch"); + foundthing= *searchfound; + + if (foundthing == newthing) { + newthing= 0; + memcpy(&sa.sin_addr,bytes,4); + r= adns_submit_reverse(ads, (const struct sockaddr*)&sa, + rrt,0,foundthing,&foundthing->qu); + if (r) adnsfail("submit",r); + } + entry= xmalloc(sizeof(*entry)); + entry->buffer= xmalloc(inbuf); + entry->textp= entry->buffer; + memcpy(entry->textp,addrtextbuf,inbuf); + entry->textlen= inbuf; + entry->addr= foundthing; + entry->printbefore= printbefore; + LIST_LINK_TAIL(outqueue,entry); + outqueuelen++; + inbuf= 0; + cbyte= -1; +} + +static void startaddr(void) { + bytes[cbyte=0]= 0; + inbyte= 0; +} + +static void readstdin(void) { + char readbuf[512], *p; + int r, c, nbyte; + + while ((r= read(0,readbuf,sizeof(readbuf))) <= 0) { + if (r == 0) { inputeof= 1; return; } + if (r == EAGAIN) return; + if (r != EINTR) sysfail("read stdin"); + } + for (p=readbuf; r>0; r--,p++) { + c= *p; + if (cbyte==-1 && bracket && c=='[') { + addrtextbuf[inbuf++]= c; + startaddr(); + } else if (cbyte==-1 && !bracket && !isalnum(c)) { + queueoutchar(c); + startaddr(); + } else if (cbyte>=0 && inbyte<3 && c>='0' && c<='9' && + (nbyte= bytes[cbyte]*10 + (c-'0')) <= 255) { + bytes[cbyte]= nbyte; + addrtextbuf[inbuf++]= c; + inbyte++; + } else if (cbyte>=0 && cbyte<3 && inbyte>0 && c=='.') { + bytes[++cbyte]= 0; + addrtextbuf[inbuf++]= c; + inbyte= 0; + } else if (cbyte==3 && inbyte>0 && bracket && c==']') { + addrtextbuf[inbuf++]= c; + procaddr(); + } else if (cbyte==3 && inbyte>0 && !bracket && !isalnum(c)) { + procaddr(); + queueoutchar(c); + startaddr(); + } else { + restartbuf(); + queueoutchar(c); + cbyte= -1; + if (!bracket && !isalnum(c)) startaddr(); + } + } + if (cbyte==3 && inbyte>0 && !bracket) procaddr(); +} + +static void startup(void) { + int r; + + if (nonblock(0,1)) sysfail("set stdin to nonblocking mode"); + if (nonblock(1,1)) sysfail("set stdout to nonblocking mode"); + memset(&sa,0,sizeof(sa)); + sa.sin_family= AF_INET; + r= adns_init(&ads,0,0); if (r) adnsfail("init",r); + cbyte= -1; + inbyte= -1; + inbuf= 0; + if (!bracket) startaddr(); +} + +int main(int argc, const char *const *argv) { + int r, maxfd; + fd_set readfds, writefds, exceptfds; + struct outqueuenode *entry; + struct timeval *tv, tvbuf, now; + + parseargs(argv); + startup(); + + while (!inputeof || outqueue.head) { + maxfd= 2; + tv= 0; + FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds); + if ((entry= outqueue.head) && !outblocked) { + if (!entry->addr) { + writestdout(entry); + continue; + } + if (entry->addr->ans) { + if (entry->addr->ans->nrrs) + replacetextwithname(entry); + entry->addr= 0; + continue; + } + r= gettimeofday(&now,0); if (r) sysfail("gettimeofday"); + if (forever) { + tv= 0; + } else if (!timercmp(&now,&entry->printbefore,<)) { + entry->addr= 0; + continue; + } else { + tvbuf.tv_sec= entry->printbefore.tv_sec - now.tv_sec - 1; + tvbuf.tv_usec= entry->printbefore.tv_usec - now.tv_usec + 1000000; + tvbuf.tv_sec += tvbuf.tv_usec / 1000000; + tvbuf.tv_usec %= 1000000; + tv= &tvbuf; + } + adns_beforeselect(ads,&maxfd,&readfds,&writefds,&exceptfds, + &tv,&tvbuf,&now); + } + if (outblocked) FD_SET(1,&writefds); + if (!inputeof && outqueuelen<1024) FD_SET(0,&readfds); + + r= select(maxfd,&readfds,&writefds,&exceptfds,tv); + if (r < 0) { if (r == EINTR) continue; else sysfail("select"); } + + r= gettimeofday(&now,0); if (r) sysfail("gettimeofday"); + adns_afterselect(ads,maxfd,&readfds,&writefds,&exceptfds,&now); + checkadnsqueries(); + + if (FD_ISSET(0,&readfds)) { + if (!forever) { + printbefore= now; + timevaladd(&printbefore,timeout); + } + readstdin(); + } else if (FD_ISSET(1,&writefds)) { + outblocked= 0; + } + } + if (nonblock(0,0)) sysfail("un-nonblock stdin"); + if (nonblock(1,0)) sysfail("un-nonblock stdout"); + if (ferror(stdin) || fclose(stdin)) sysfail("read stdin"); + if (fclose(stdout)) sysfail("close stdout"); + exit(0); +} Index: adns/client/adnstest.c diff -u adns/client/adnstest.c:1.38 adns/client/adnstest.c:1.39 --- adns/client/adnstest.c:1.38 Sun Oct 10 14:16:24 1999 +++ adns/client/adnstest.c Tue Nov 2 23:40:14 1999 @@ -41,11 +41,30 @@ # define OUTPUTSTREAM stdout #endif +struct myctx { + adns_query qu; + int doneyet, found; + const char *fdom; +}; + +static struct myctx *mcs; +static adns_state ads; +static adns_rrtype *types_a; + +static void quitnow(int rc) NONRETURNING; +static void quitnow(int rc) { + free(mcs); + free(types_a); + if (ads) adns_finish(ads); + + exit(rc); +} + #ifndef HAVE_POLL #undef poll int poll(struct pollfd *ufds, int nfds, int timeout) { fputs("poll(2) not supported on this system\n",stderr); - exit(5); + quitnow(5); } #define adns_beforepoll(a,b,c,d,e) 0 #define adns_afterpoll(a,b,c,d) 0 @@ -54,13 +73,13 @@ static void failure_status(const char *what, adns_status st) NONRETURNING; static void failure_status(const char *what, adns_status st) { fprintf(stderr,"adns failure: %s: %s\n",what,adns_strerror(st)); - exit(2); + quitnow(2); } static void failure_errno(const char *what, int errnoval) NONRETURNING; static void failure_errno(const char *what, int errnoval) { fprintf(stderr,"adns failure: %s: errno=%d\n",what,errnoval); - exit(2); + quitnow(2); } static void usageerr(const char *why) NONRETURNING; @@ -80,7 +99,7 @@ " 4 usage error\n" " 5 operation not supported on this system\n", why); - exit(4); + quitnow(4); } static const adns_rrtype defaulttypes[]= { @@ -120,7 +139,7 @@ if (*ep == ',' && strchr(ep,'/')) { ep++; while (*ep != '/') { - if (--ownflags_l <= 0) { fputs("too many flags\n",stderr); exit(3); } + if (--ownflags_l <= 0) { fputs("too many flags\n",stderr); quitnow(3); } *ownflags++= *ep++; } } @@ -134,15 +153,8 @@ } int main(int argc, char *const *argv) { - struct myctx { - adns_query qu; - int doneyet, found; - const char *fdom; - }; - - adns_state ads; adns_query qu; - struct myctx *mcs, *mc, *mcw; + struct myctx *mc, *mcw; void *mcr; adns_answer *ans; const char *initstring, *rrtn, *fmtn; @@ -153,7 +165,6 @@ int r; const adns_rrtype *types; struct timeval now; - adns_rrtype *types_a; char ownflags[10]; char *ep; const char *initflags, *owninitflags; @@ -185,7 +196,7 @@ for (cp= argv[1]+1, tc=1; (ch= *cp); cp++) if (ch==',') tc++; types_a= malloc(sizeof(*types_a)*(tc+1)); - if (!types_a) { perror("malloc types"); exit(3); } + if (!types_a) { perror("malloc types"); quitnow(3); } for (cp= argv[1]+1, ti=0; tifdom,&domain,&qflags,ownflags,sizeof(ownflags)); - if (gettimeofday(&now,0)) { perror("gettimeofday"); exit(3); } + if (gettimeofday(&now,0)) { perror("gettimeofday"); quitnow(3); } ri= adns_rr_info(ans->type, &rrtn,&fmtn,&len, 0,0); fprintf(stdout, "%s flags %d type ",domain,qflags); @@ -321,8 +333,5 @@ mc->doneyet= 1; } - free(mcs); - adns_finish(ads); - - exit(0); + quitnow(0); } Index: adns/client/fanftest.c diff -u /dev/null adns/client/fanftest.c:1.2 --- /dev/null Wed Nov 24 17:20:58 1999 +++ adns/client/fanftest.c Fri Oct 15 17:46:57 1999 @@ -0,0 +1,85 @@ +/* + * fanftest.c + * - a small test program from Tony Finch + */ +/* + * This file is + * Copyright (C) 1999 Tony Finch + * Copyright (C) 1999 Ian Jackson + * + * It is part of adns, which is + * Copyright (C) 1997-1999 Ian Jackson + * Copyright (C) 1999 Tony Finch + * + * 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. + * + * This version was originally supplied by Tony Finch, but has been + * modified by Ian Jackson as it was incorporated into adns. + */ + +static const char * const cvsid = + "$Id: fanftest.c,v 1.2 1999/10/15 16:46:57 ian Exp $"; + +#include +#include + +#include +#include +#include +#include + +#include "adns.h" + +static const char *progname; + +static void aargh(const char *msg) { + fprintf(stderr, "%s: %s: %s (%d)\n", progname, msg, + strerror(errno) ? strerror(errno) : "Unknown error", errno); + exit(1); +} + +int main(int argc, char *argv[]) { + adns_state adns; + adns_query query; + adns_answer *answer; + + progname= strrchr(*argv, '/'); + if (progname) + progname++; + else + progname= *argv; + + if (argc != 2) { + fprintf(stderr, "usage: %s \n", progname); + exit(1); + } + + errno= adns_init(&adns, adns_if_debug, 0); + if (errno) aargh("adns_init"); + + errno= adns_submit(adns, argv[1], adns_r_ptr, + adns_qf_quoteok_cname|adns_qf_cname_loose, + NULL, &query); + if (errno) aargh("adns_submit"); + + errno= adns_wait(adns, &query, &answer, NULL); + if (errno) aargh("adns_init"); + + printf("%s\n", answer->status == adns_s_ok ? *answer->rrs.str : "dunno"); + + adns_finish(adns); + + return 0; +} Index: adns/client/x.gdb diff -u /dev/null adns/client/x.gdb:1.1 --- /dev/null Wed Nov 24 17:20:58 1999 +++ adns/client/x.gdb Sun Nov 7 19:02:20 1999 @@ -0,0 +1,2 @@ +file adnsresfilter_s +set args #include #include +#include #include #include @@ -51,6 +52,9 @@ { "ENOPROTOOPT", ENOPROTOOPT }, { "ENOSPC", ENOSPC }, { "EWOULDBLOCK", EWOULDBLOCK }, + { "EHOSTUNREACH", EHOSTUNREACH }, + { "ECONNREFUSED", ECONNREFUSED }, + { "EPIPE", EPIPE }, { 0, 0 } }; @@ -128,7 +132,7 @@ const byte *bp; int i; - if (!len) { Tvba(" empty"); return; } + if (!len) { Tvba("\n ."); return; } for (i=0, bp=buf; idata - (char*)mallocedlist.head) + +void *Hmalloc(size_t sz) { + struct malloced *newnode; + const char *mfavar; + char *ep; + + assert(sz); + + newnode= malloc(MALLOCHSZ + sz); if (!newnode) Tnomem(); + + LIST_LINK_TAIL(mallocedlist,newnode); + newnode->sz= sz; + newnode->count= ++malloccount; + if (!mallocfailat) { + mfavar= getenv("ADNS_REGRESS_MALLOCFAILAT"); + if (mfavar) { + mallocfailat= strtoul(mfavar,&ep,10); + if (!mallocfailat || *ep) Tfailed("ADNS_REGRESS_MALLOCFAILAT bad value"); + } else { + mallocfailat= ~0UL; + } + } + assert(newnode->count != mallocfailat); + memset(&newnode->data,0xc7,sz); + return &newnode->data; +} + +void Hfree(void *ptr) { + struct malloced *oldnode; + + if (!ptr) return; + + oldnode= (void*)((char*)ptr - MALLOCHSZ); + LIST_UNLINK(mallocedlist,oldnode); + memset(&oldnode->data,0x38,oldnode->sz); + free(oldnode); +} + +void *Hrealloc(void *op, size_t nsz) { + struct malloced *oldnode; + void *np; + size_t osz; + + if (op) { oldnode= (void*)((char*)op - MALLOCHSZ); osz= oldnode->sz; } else { osz= 0; } + np= Hmalloc(nsz); + memcpy(np,op, osz>nsz ? nsz : osz); + Hfree(op); + return np; +} + +void Hexit(int rv) { + struct malloced *loopnode; + + Tshutdown(); + adns__vbuf_free(&vb); + adns__vbuf_free(&vbw); + if (mallocedlist.head) { + fprintf(stderr,"adns test harness: memory leaked:"); + for (loopnode=mallocedlist.head; loopnode; loopnode=loopnode->next) + fprintf(stderr," %lu(%lu)",loopnode->count,(unsigned long)loopnode->sz); + putc('\n',stderr); + if (ferror(stderr)) exit(-1); + } + exit(rv); } Index: adns/regress/hplayback.c.m4 diff -u adns/regress/hplayback.c.m4:1.9 adns/regress/hplayback.c.m4:1.11 --- adns/regress/hplayback.c.m4:1.9 Tue Oct 12 22:28:29 1999 +++ adns/regress/hplayback.c.m4 Tue Nov 2 23:40:14 1999 @@ -40,10 +40,15 @@ static FILE *Tinputfile, *Treportfile; static vbuf vb2; +extern void Tshutdown(void) { + adns__vbuf_free(&vb2); +} + static void Tensurereportfile(void) { const char *fdstr; int fd; + if (Treportfile) return; Treportfile= stderr; fdstr= getenv("ADNS_TEST_REPORT_FD"); if (!fdstr) return; fd= atoi(fdstr); @@ -271,7 +276,7 @@ m4_define(`hm_syscall', ` hm_create_proto_h int H$1(hm_args_massage($3,void)) { - int r; + int r, amtread; m4_define(`hm_rv_fd',`char *ep;') m4_define(`hm_rv_any',`char *ep;') m4_define(`hm_rv_len',`') @@ -295,10 +300,10 @@ Tensurereportfile(); fprintf(Treportfile,"syscallr %s",vb2.buf); - vb2.avail= strlen(vb2.buf); - if (vb.avail<=0 || vb2.buf[--vb2.avail]!=hm_squote\nhm_squote) + amtread= strlen(vb2.buf); + if (amtread<=0 || vb2.buf[--amtread]!=hm_squote\nhm_squote) Psyntax("badly formed line"); - vb2.buf[vb2.avail]= 0; + vb2.buf[amtread]= 0; if (memcmp(vb2.buf," $1=",hm_r_offset)) Psyntax("syscall reply mismatch"); if (vb2.buf[hm_r_offset] == hm_squoteEhm_squote) { @@ -346,7 +351,8 @@ m4_define(`hm_arg_pollfds_io',`Parg("$'`1"); Ppollfds($'`1,$'`2);') m4_define(`hm_arg_addr_out',`Parg("$'`1"); Paddr($'`1,$'`2);') $3 - if (vb2.used != vb2.avail) Psyntax("junk at end of line"); + assert(vb2.used <= amtread); + if (vb2.used != amtread) Psyntax("junk at end of line"); hm_create_nothing m4_define(`hm_arg_bytes_out',`r= Pbytes($'`2,$'`4);') Index: adns/regress/hrecord.c.m4 diff -u adns/regress/hrecord.c.m4:1.10 adns/regress/hrecord.c.m4:1.11 --- adns/regress/hrecord.c.m4:1.10 Sun Oct 10 14:16:24 1999 +++ adns/regress/hrecord.c.m4 Tue Nov 2 23:40:14 1999 @@ -35,6 +35,9 @@ static FILE *Toutputfile; +void Tshutdown(void) { +} + static void R_recordtime(void) { int r; struct timeval tv, tvrel; Index: adns/regress/init-1stservbroken.text diff -u /dev/null adns/regress/init-1stservbroken.text:1.1 --- /dev/null Wed Nov 24 17:20:58 1999 +++ adns/regress/init-1stservbroken.text Sat Oct 16 20:04:07 1999 @@ -0,0 +1,3 @@ +nameserver 172.18.45.2 +nameserver 172.18.45.6 +sortlist 127.0.0.1/32 172.18.45.0/28 172.18.45.0/24 Index: adns/regress/init-1stservto.text diff -u /dev/null adns/regress/init-1stservto.text:1.1 --- /dev/null Wed Nov 24 17:20:58 1999 +++ adns/regress/init-1stservto.text Sat Oct 16 20:04:07 1999 @@ -0,0 +1,3 @@ +nameserver 10.0.0.1 +nameserver 172.18.45.6 +sortlist 127.0.0.1/32 172.18.45.0/28 172.18.45.0/24 Index: adns/regress/init-2ndserver.text diff -u /dev/null adns/regress/init-2ndserver.text:1.1 --- /dev/null Wed Nov 24 17:20:58 1999 +++ adns/regress/init-2ndserver.text Sat Oct 16 20:04:07 1999 @@ -0,0 +1,3 @@ +nameserver 172.18.45.36 +nameserver 172.18.45.6 +sortlist 127.0.0.1/32 172.18.45.0/28 172.18.45.0/24 Index: adns/src/adns.h diff -u adns/src/adns.h:1.70 adns/src/adns.h:1.73 --- adns/src/adns.h:1.70 Wed Oct 13 02:23:56 1999 +++ adns/src/adns.h Sun Nov 7 19:15:36 1999 @@ -51,7 +51,7 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * - * $Id: adns.h,v 1.70 1999/10/13 01:23:56 ian Exp $ + * $Id: adns.h,v 1.73 1999/11/07 19:15:36 ian Exp $ */ #ifndef ADNS_H_INCLUDED @@ -78,6 +78,7 @@ 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 */ @@ -336,20 +337,21 @@ * requested. */ -int adns_init(adns_state *newstate_r, int flags /*adns_initflags*/, +int adns_init(adns_state *newstate_r, adns_initflags flags, FILE *diagfile /*0=>stderr*/); -int adns_init_strcfg(adns_state *newstate_r, int flags /*adns_initflags*/, +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. adns_init_strcfg - * is instead passed a string which is interpreted as if it were the - * contents of resolv.conf. In general, configuration which is set - * later overrides any that is set earlier. + * 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.conf: + * Standard directives understood in resolv[-adns].conf: * * nameserver
* Must be followed by the IP address of a nameserver. Several @@ -382,7 +384,7 @@ * 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.conf: + * Non-standard directives understood in resolv[-adns].conf: * * clearnameservers * Clears the list of nameservers, so that further nameserver lines @@ -391,7 +393,8 @@ * include * The specified file will be read. * - * Additionally, adns will ignore lines in resolv.conf which start with a #. + * Additionally, adns will ignore lines in resolv[-adns].conf which + * start with a #. * * Standard options understood: * @@ -420,7 +423,7 @@ * 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.conf is read, in the order they are listed here. + * 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. @@ -443,7 +446,7 @@ int adns_synchronous(adns_state ads, const char *owner, adns_rrtype type, - int flags /*adns_queryflags*/, + adns_queryflags flags, adns_answer **answer_r); /* NB: if you set adns_if_noautosys then _submit and _check do not @@ -454,7 +457,7 @@ int adns_submit(adns_state ads, const char *owner, adns_rrtype type, - int flags /*adns_queryflags*/, + adns_queryflags flags, void *context, adns_query *query_r); @@ -493,7 +496,7 @@ int adns_submit_reverse(adns_state ads, const struct sockaddr *addr, adns_rrtype type, - int flags /*adns_queryflags*/, + adns_queryflags flags, void *context, adns_query *query_r); /* type must be _r_ptr or _r_ptr_raw. _qf_search is ignored. Index: adns/src/check.c diff -u adns/src/check.c:1.5 adns/src/check.c:1.6 --- adns/src/check.c:1.5 Tue Oct 12 20:51:08 1999 +++ adns/src/check.c Sat Oct 16 20:11:02 1999 @@ -63,12 +63,16 @@ assert(qu->udpnextserver < ads->nservers); assert(!(qu->udpsent & (~0UL << ads->nservers))); - assert(!(qu->tcpfailed & (~0UL << ads->nservers))); - assert(qu->udpretries <= UDPMAXRETRIES); 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; @@ -82,10 +86,12 @@ switch (ads->tcpstate) { case server_connecting: assert(ads->tcpsocket >= 0); - case server_disconnected: /* fall through */ - assert(!ads->tcpsend.used); - assert(!ads->tcprecv.used); - assert(!ads->tcprecv_skip); + 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); @@ -98,34 +104,36 @@ assert(ads->searchlist || !ads->nsearchlist); } -static void checkc_queue_timew(adns_state ads) { +static void checkc_queue_udpw(adns_state ads) { adns_query qu; - DLIST_CHECK(ads->timew, qu, , { - switch (qu->state) { - case query_tosend: - assert(qu->udpsent); - assert(!qu->tcpfailed); - break; - case query_tcpwait: - assert(ads->tcpstate != server_ok); - break; - case query_tcpsent: - break; - default: - assert(!"timew state"); - } + 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_child); + assert(parent->state == query_childw); assert(parent->children.head); DLIST_CHECK(parent->children, child, siblings., { assert(child->parent == parent); @@ -165,18 +173,20 @@ } checkc_global(ads); - checkc_queue_timew(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: - case query_tcpwait: - case query_tcpsent: - DLIST_ASSERTON(qu, search, ads->timew, ); + DLIST_ASSERTON(qu, search, ads->udpw, ); + break; + case query_tcpw: + DLIST_ASSERTON(qu, search, ads->tcpw, ); break; - case query_child: + case query_childw: DLIST_ASSERTON(qu, search, ads->childw, ); break; case query_done: Index: adns/src/event.c diff -u adns/src/event.c:1.40 adns/src/event.c:1.44 --- adns/src/event.c:1.40 Wed Oct 13 00:00:08 1999 +++ adns/src/event.c Sun Nov 7 16:06:48 1999 @@ -39,40 +39,29 @@ #include #include "internal.h" +#include "tvarith.h" /* TCP connection management. */ -void adns__tcp_closenext(adns_state ads) { +static void tcp_close(adns_state ads) { int serv; serv= ads->tcpserver; close(ads->tcpsocket); ads->tcpsocket= -1; - ads->tcpstate= server_disconnected; ads->tcprecv.used= ads->tcprecv_skip= ads->tcpsend.used= 0; - ads->tcpserver= (serv+1)%ads->nservers; } void adns__tcp_broken(adns_state ads, const char *what, const char *why) { int serv; - adns_query qu, nqu; assert(ads->tcpstate == server_connecting || ads->tcpstate == server_ok); serv= ads->tcpserver; - adns__warn(ads,serv,0,"TCP connection lost: %s: %s",what,why); - adns__tcp_closenext(ads); - - for (qu= ads->timew.head; qu; qu= nqu) { - nqu= qu->next; - if (qu->state == query_tosend) continue; - assert(qu->state == query_tcpwait || qu->state == query_tcpsent); - qu->state= query_tcpwait; - qu->tcpfailed |= (1<tcpfailed == (1<nservers)-1) { - LIST_UNLINK(ads->timew,qu); - adns__query_fail(qu,adns_s_allservfail); - } - } + 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) { @@ -80,11 +69,10 @@ adns__debug(ads,ads->tcpserver,0,"TCP connected"); ads->tcpstate= server_ok; - for (qu= ads->timew.head; qu; qu= nqu) { + for (qu= ads->tcpw.head; qu && ads->tcpstate == server_ok; qu= nqu) { nqu= qu->next; - if (qu->state == query_tosend) continue; - assert (qu->state == query_tcpwait); - adns__query_tcp(qu,now); + assert(qu->state == query_tcpw); + adns__querysend_tcp(qu,now); } } @@ -94,8 +82,17 @@ struct protoent *proto; for (tries=0; triesnservers; tries++) { - if (ads->tcpstate == server_connecting || ads->tcpstate == server_ok) return; - assert(ads->tcpstate == server_disconnected); + 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); @@ -120,9 +117,14 @@ r= connect(fd,(const struct sockaddr*)&addr,sizeof(addr)); ads->tcpsocket= fd; ads->tcpstate= server_connecting; - if (r==0) { tcp_connected(ads,now); continue; } - if (errno == EWOULDBLOCK || errno == EINPROGRESS) return; + 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; } } @@ -158,6 +160,7 @@ 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", @@ -172,29 +175,94 @@ inter_maxto(tv_io,tvbuf,maxtime); } -void adns__timeouts(adns_state ads, int act, - struct timeval **tv_io, struct timeval *tvbuf, - struct timeval now) { +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= ads->timew.head; qu; qu= nqu) { + + for (qu= queue->head; qu; qu= nqu) { nqu= qu->next; if (!timercmp(&now,&qu->timeout,>)) { - if (!tv_io) continue; inter_maxtoabs(tv_io,tvbuf,now,qu->timeout); } else { - if (!act) continue; - LIST_UNLINK(ads->timew,qu); + 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= ads->timew.head; + 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) { @@ -509,14 +577,13 @@ void adns_globalsystemfailure(adns_state ads) { adns__consistency(ads,0,cc_entex); - while (ads->timew.head) { - adns__query_fail(ads->timew.head, adns_s_systemfail); - } + 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_closenext(ads); + adns__tcp_broken(ads,0,0); break; case server_disconnected: break; @@ -567,7 +634,7 @@ if (!qu) { if (ads->output.head) { qu= ads->output.head; - } else if (ads->timew.head) { + } else if (ads->udpw.head || ads->tcpw.head) { return EAGAIN; } else { return ESRCH; Index: adns/src/general.c diff -u adns/src/general.c:1.23 adns/src/general.c:1.25 --- adns/src/general.c:1.23 Wed Oct 13 01:23:01 1999 +++ adns/src/general.c Tue Nov 2 23:40:14 1999 @@ -27,6 +27,7 @@ */ #include +#include #include #include @@ -46,7 +47,11 @@ (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent)))) return; - fprintf(ads->diagfile,"adns%s: ",pfx); + 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); @@ -63,6 +68,7 @@ if (qu->typei && qu->typei->fmtname) fprintf(ads->diagfile,"(%s)",qu->typei->fmtname); bef=", "; aft=")\n"; + adns__vbuf_free(&vb); } if (serv>=0) { Index: adns/src/internal.h diff -u adns/src/internal.h:1.51 adns/src/internal.h:1.54 --- adns/src/internal.h:1.51 Tue Oct 12 20:51:08 1999 +++ adns/src/internal.h Sun Nov 7 16:06:49 1999 @@ -11,20 +11,20 @@ * It is part of adns, which is * Copyright (C) 1997-1999 Ian Jackson * Copyright (C) 1999 Tony Finch - * + * * 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. + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ADNS_INTERNAL_H_INCLUDED @@ -51,7 +51,9 @@ #define MAXSORTLIST 15 #define UDPMAXRETRIES 15 #define UDPRETRYMS 2000 -#define TCPMS 30000 +#define TCPWAITMS 30000 +#define TCPCONNMS 14000 +#define TCPIDLEMS 30000 #define MAXTTLBELIEVE (7*86400) /* any TTL > 7 days is capped */ #define DNS_PORT 53 @@ -164,7 +166,7 @@ struct adns__query { adns_state ads; - enum { query_tosend, query_tcpwait, query_tcpsent, query_child, query_done } state; + 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; @@ -175,7 +177,7 @@ 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 @@ -192,7 +194,7 @@ * 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 . */ @@ -207,10 +209,10 @@ * 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, udpretries; + + int id, flags, retries; int udpnextserver; - unsigned long udpsent, tcpfailed; /* bitmap indexed by server */ + unsigned long udpsent; /* bitmap indexed by server */ struct timeval timeout; time_t expires; /* Earliest expiry time of any record we used. */ @@ -219,43 +221,41 @@ /* Possible states: * * state Queue child id nextudpserver udpsent tcpfailed - * + * * tosend NONE null >=0 0 zero zero - * tosend timew null >=0 any nonzero zero + * tosend udpw null >=0 any nonzero zero * tosend NONE null >=0 any nonzero zero - * - * tcpwait timew null >=0 irrelevant any any - * tcpsent timew null >=0 irrelevant any any - * + * + * 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 -----> | udp/NONE | + * START -----> | tosend/NONE | * +------------------------+ * / |\ \ * too big for UDP / UDP timeout \ \ send via UDP - * do this ASAP! / more retries \ \ do this ASAP! - * |_ desired \ _| - * +---------------+ +-----------+ - * | tcpwait/timew | ____ | udp/timew | - * +---------------+ \ +-----------+ - * | ^ | | | - * TCP conn'd; | | TCP died | | | - * send via TCP | | more | UDP timeout | | - * do this ASAP! | | servers | no more | | - * v | to try | retries | | - * +---------------+ | desired | | - * | tcpsent/timew | ____ | | | - * +---------------+ \| | | - * \ \ TCP died | TCP | | - * \ \ no more | timeout / | - * \ \ servers | / | - * \ \ to try | / | - * got \ \ v |_ / got + * 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 | / * \ +------------------+ / @@ -266,23 +266,33 @@ * need child query/ies / \ no child query * / \ * |_ _| - * +--------------+ +----------------+ - * | child/childw | ----------------> | done/output OK | - * +--------------+ children done +----------------+ + * +---------------+ +----------------+ + * | 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 { adns_query head, tail; } timew, childw, output; + 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 } tcpstate; + 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]; @@ -298,7 +308,6 @@ /* From setup.c: */ int adns__setnonblock(adns_state ads, int fd); /* => errno value */ -void adns__checkqueues(adns_state ads); /* expensive walk, for checking */ /* From general.c: */ @@ -332,7 +341,7 @@ * 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); @@ -347,7 +356,8 @@ /* 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. + * any significant amount of code gets to run, since the old signal mask + * is stored in the adns structure. */ /* From transmit.c: */ @@ -365,16 +375,10 @@ * That domain must be correct and untruncated. */ -void adns__query_tcp(adns_query qu, struct timeval now); -/* Query must be in state tcpwait/timew; it will be moved to a new state - * if possible and no further processing can be done on it for now. - * (Resulting state is one of tcpwait/timew (if server not connected), - * tcpsent/timew, child/childw or done/output.) - * - * adns__tcp_tryconnect should already have been called - _tcp - * will only use an existing connection (if there is one), which it - * may break. If the conn list lost then the caller is responsible for any - * reestablishment and retry. +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); @@ -488,11 +492,19 @@ 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: */ @@ -628,7 +640,8 @@ /* From event.c: */ void adns__tcp_broken(adns_state ads, const char *what, const char *why); -void adns__tcp_closenext(adns_state ads); +/* 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); @@ -639,9 +652,7 @@ void adns__must_gettimeofday(adns_state ads, const struct timeval **now_io, struct timeval *tv_buf); -void adns__timeouts(adns_state ads, int act, - struct timeval **tv_io, struct timeval *tvbuf, - struct timeval now); + int adns__pollfds(adns_state ads, struct pollfd pollfds_buf[MAX_POLLFDS]); void adns__fdevents(adns_state ads, const struct pollfd *pollfds, int npollfds, @@ -653,21 +664,18 @@ 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 void timevaladd(struct timeval *tv_io, long ms) { - struct timeval tmp; - assert(ms>=0); - tmp= *tv_io; - tmp.tv_usec += (ms%1000)*1000000; - tmp.tv_sec += ms/1000; - if (tmp.tv_usec >= 1000000) { tmp.tv_sec++; tmp.tv_usec -= 1000; } - *tv_io= tmp; -} 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'; } Index: adns/src/query.c diff -u adns/src/query.c:1.48 adns/src/query.c:1.53 --- adns/src/query.c:1.48 Wed Oct 13 02:23:56 1999 +++ adns/src/query.c Tue Nov 2 23:40:14 1999 @@ -68,9 +68,9 @@ qu->id= 0; qu->flags= flags; - qu->udpretries= 0; + qu->retries= 0; qu->udpnextserver= 0; - qu->udpsent= qu->tcpfailed= 0; + qu->udpsent= 0; timerclear(&qu->timeout); qu->expires= now.tv_sec + MAXTTLBELIEVE; @@ -91,7 +91,7 @@ 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. + * and submits it. Cannot fail. Takes over the memory for qumsg_vb. */ qu->vb= *qumsg_vb; @@ -131,7 +131,7 @@ int id; adns_status stat; - adns__vbuf_init(&vb); + vb= qu->vb; stat= adns__mkquery(ads,&vb,&id, owner,ol, typei,flags); if (stat) { adns__query_fail(qu,stat); return; } @@ -195,7 +195,7 @@ int adns_submit(adns_state ads, const char *owner, adns_rrtype type, - int flags, + adns_queryflags flags, void *context, adns_query *query_r) { int r, ol, ndots; @@ -225,6 +225,7 @@ if (ol>=1 && owner[ol-1]=='.' && (ol<2 || owner[ol-2]!='\\')) { flags &= ~adns_qf_search; + qu->flags= flags; ol--; } @@ -261,7 +262,7 @@ int adns_submit_reverse(adns_state ads, const struct sockaddr *addr, adns_rrtype type, - int flags, + adns_queryflags flags, void *context, adns_query *query_r) { const unsigned char *iaddr; @@ -282,7 +283,7 @@ int adns_synchronous(adns_state ads, const char *owner, adns_rrtype type, - int flags, + adns_queryflags flags, adns_answer **answer_r) { adns_query qu; int r; @@ -389,6 +390,8 @@ 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) { @@ -398,10 +401,13 @@ adns__consistency(ads,qu,cc_entex); if (qu->parent) LIST_UNLINK_PART(qu->parent->children,qu,siblings.); switch (qu->state) { - case query_tosend: case query_tcpwait: case query_tcpsent: - LIST_UNLINK(ads->timew,qu); + case query_tosend: + LIST_UNLINK(ads->udpw,qu); + break; + case query_tcpw: + LIST_UNLINK(ads->tcpw,qu); break; - case query_child: + case query_childw: LIST_UNLINK(ads->childw,qu); break; case query_done: @@ -496,6 +502,7 @@ LIST_UNLINK(qu->ads->childw,parent); qu->ctx.callback(parent,qu); free_query_allocs(qu); + free(qu->answer); free(qu); } else { makefinal_query(qu); Index: adns/src/reply.c diff -u adns/src/reply.c:1.33 adns/src/reply.c:1.34 --- adns/src/reply.c:1.33 Sun Oct 10 14:16:24 1999 +++ adns/src/reply.c Sat Oct 16 20:11:02 1999 @@ -85,7 +85,7 @@ qdcount); return; } - for (qu= ads->timew.head; qu; qu= nqu) { + 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; @@ -94,9 +94,9 @@ qu->query_dglen-DNS_HDRSIZE)) continue; if (viatcp) { - if (qu->state != query_tcpsent) continue; + assert(qu->state == query_tcpw); } else { - if (qu->state != query_tosend) continue; + assert(qu->state == query_tosend); if (!(qu->udpsent & (1<query_dglen; arstart= -1; - LIST_UNLINK(ads->timew,qu); + 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) { @@ -318,7 +319,7 @@ /* This may have generated some child queries ... */ if (qu->children.head) { - qu->state= query_child; + qu->state= query_childw; LIST_LINK_TAIL(ads->childw,qu); return; } @@ -349,7 +350,8 @@ memcpy(newquery,qu->vb.buf,qu->vb.used); } - if (qu->state == query_tcpsent) qu->state= query_tosend; + if (qu->state == query_tcpw) qu->state= query_tosend; + qu->retries= 0; adns__reset_preserved(qu); adns__query_send(qu,now); } Index: adns/src/setup.c diff -u adns/src/setup.c:1.30 adns/src/setup.c:1.35 --- adns/src/setup.c:1.30 Wed Oct 13 02:23:56 1999 +++ adns/src/setup.c Sun Nov 7 19:15:36 1999 @@ -39,7 +39,7 @@ #include "internal.h" -static void readconfig(adns_state ads, const char *filename); +static void readconfig(adns_state ads, const char *filename, int warnmissing); static void addserver(adns_state ads, struct in_addr addr) { int i; @@ -62,6 +62,11 @@ 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; } @@ -133,7 +138,7 @@ *newchars++ = 0; } - free(ads->searchlist); + freesearchlist(ads); ads->nsearchlist= count; ads->searchlist= newptrs; } @@ -259,7 +264,7 @@ configparseerr(ads,fn,lno,"`include' directive with no filename"); return; } - readconfig(ads,buf); + readconfig(ads,buf,1); } static const struct configcommandinfo { @@ -394,13 +399,14 @@ return value; } -static void readconfig(adns_state ads, const char *filename) { +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) { - adns__debug(ads,-1,0,"configuration file `%s' does not exist",filename); + if (warnmissing) + adns__debug(ads,-1,0,"configuration file `%s' does not exist",filename); return; } saveerr(ads,errno); @@ -429,7 +435,7 @@ return; } filename= instrum_getenv(ads,envvar); - if (filename) readconfig(ads,filename); + if (filename) readconfig(ads,filename,1); } static void readconfigenvtext(adns_state ads, const char *envvar) { @@ -461,7 +467,8 @@ ads->iflags= flags; ads->diagfile= diagfile; ads->configerrno= 0; - LIST_INIT(ads->timew); + LIST_INIT(ads->udpw); + LIST_INIT(ads->tcpw); LIST_INIT(ads->childw); LIST_INIT(ads->output); ads->forallnext= 0; @@ -516,7 +523,7 @@ free(ads); } -int adns_init(adns_state *ads_r, int flags, FILE *diagfile) { +int adns_init(adns_state *ads_r, adns_initflags flags, FILE *diagfile) { adns_state ads; const char *res_options, *adns_res_options; int r; @@ -529,7 +536,8 @@ ccf_options(ads,"RES_OPTIONS",-1,res_options); ccf_options(ads,"ADNS_RES_OPTIONS",-1,adns_res_options); - readconfig(ads,"/etc/resolv.conf"); + readconfig(ads,"/etc/resolv.conf",1); + readconfig(ads,"/etc/resolv-adns.conf",0); readconfigenv(ads,"RES_CONF"); readconfigenv(ads,"ADNS_RES_CONF"); @@ -556,7 +564,7 @@ return 0; } -int adns_init_strcfg(adns_state *ads_r, int flags, +int adns_init_strcfg(adns_state *ads_r, adns_initflags flags, FILE *diagfile, const char *configtext) { adns_state ads; int r; @@ -580,7 +588,8 @@ void adns_finish(adns_state ads) { adns__consistency(ads,0,cc_entex); for (;;) { - if (ads->timew.head) adns_cancel(ads->timew.head); + 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; @@ -589,13 +598,15 @@ 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->timew.head ? ads->timew.head : + ads->udpw.head ? ads->udpw.head : + ads->tcpw.head ? ads->tcpw.head : ads->childw.head ? ads->childw.head : ads->output.head; } @@ -610,12 +621,15 @@ if (!qu) return 0; if (qu->next) { nqu= qu->next; - } else if (qu == ads->timew.tail) { - if (ads->childw.head) { - nqu= ads->childw.head; - } else { - nqu= ads->output.head; - } + } 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 { @@ -626,9 +640,4 @@ ads->forallnext= nqu; if (context_r) *context_r= qu->ctx.ext; return qu; -} - -void adns__checkqueues(adns_state ads) { - adns_forallqueries_begin(ads); - while (adns_forallqueries_next(ads,0)); } Index: adns/src/transmit.c diff -u adns/src/transmit.c:1.14 adns/src/transmit.c:1.17 --- adns/src/transmit.c:1.14 Sun Oct 10 14:16:24 1999 +++ adns/src/transmit.c Sun Nov 7 16:06:49 1999 @@ -32,6 +32,7 @@ #include #include "internal.h" +#include "tvarith.h" #define MKQUERY_START(vb) (rqp= (vb)->buf+(vb)->used) #define MKQUERY_ADDB(b) *rqp++= (b) @@ -81,7 +82,7 @@ const char *p, *pe; adns_status st; - st= mkquery_header(ads,vb,id_r,strlen(owner)+2); if (st) return st; + st= mkquery_header(ads,vb,id_r,ol+2); if (st) return st; MKQUERY_START(vb); @@ -157,7 +158,7 @@ return adns_s_ok; } -void adns__query_tcp(adns_query qu, struct timeval now) { +void adns__querysend_tcp(adns_query qu, struct timeval now) { byte length[2]; struct iovec iov[2]; int wr, r; @@ -165,15 +166,18 @@ 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; - timevaladd(&now,TCPMS); - qu->timeout= now; - qu->state= query_tcpsent; + qu->retries++; + + /* Reset idle timeout. */ + ads->tcptimeout.tv_sec= ads->tcptimeout.tv_usec= 0; if (ads->tcpsend.used) { wr= 0; @@ -207,11 +211,11 @@ } static void query_usetcp(adns_query qu, struct timeval now) { - timevaladd(&now,TCPMS); + qu->state= query_tcpw; qu->timeout= now; - qu->state= query_tcpwait; - LIST_LINK_TAIL(qu->ads->timew,qu); - adns__query_tcp(qu,now); + timevaladd(&qu->timeout,TCPWAITMS); + LIST_LINK_TAIL(qu->ads->tcpw,qu); + adns__querysend_tcp(qu,now); adns__tcp_tryconnect(qu->ads,now); } @@ -226,7 +230,7 @@ return; } - if (qu->udpretries >= UDPMAXRETRIES) { + if (qu->retries >= UDPMAXRETRIES) { adns__query_fail(qu,adns_s_timeout); return; } @@ -241,13 +245,13 @@ r= sendto(ads->udpsocket,qu->query_dgram,qu->query_dglen,0, (const struct sockaddr*)&servaddr,sizeof(servaddr)); - if (r<0 && errno == EMSGSIZE) { query_usetcp(qu,now); return; } + 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)); - timevaladd(&now,UDPRETRYMS); qu->timeout= now; + timevaladd(&qu->timeout,UDPRETRYMS); qu->udpsent |= (1<udpnextserver= (serv+1)%ads->nservers; - qu->udpretries++; - LIST_LINK_TAIL(ads->timew,qu); + qu->retries++; + LIST_LINK_TAIL(ads->udpw,qu); } Index: adns/src/tvarith.h diff -u /dev/null adns/src/tvarith.h:1.2 --- /dev/null Wed Nov 24 17:20:58 1999 +++ adns/src/tvarith.h Sun Nov 7 19:02:20 1999 @@ -0,0 +1,41 @@ +/* + * tvarith.h + * - static inline functions for doing arithmetic on timevals + */ +/* + * This file is + * Copyright (C) 1997-1999 Ian Jackson + * + * It is part of adns, which is + * Copyright (C) 1997-1999 Ian Jackson + * Copyright (C) 1999 Tony Finch + * + * 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