diff options
author | Robert James Kaes <rjkaes@users.sourceforge.net> | 2000-09-12 00:38:47 +0000 |
---|---|---|
committer | Robert James Kaes <rjkaes@users.sourceforge.net> | 2000-09-12 00:38:47 +0000 |
commit | 15ea792c424fc1daa2e36e63c5c7474a45b73161 (patch) | |
tree | 51c7599757a01151bca28fc2987ea9aed020dba8 /adns-0.6/src | |
parent | 7a949c9470c6bd12132f228af14d5ea23f0be37c (diff) | |
download | tinyproxy-15ea792c424fc1daa2e36e63c5c7474a45b73161.tar.gz tinyproxy-15ea792c424fc1daa2e36e63c5c7474a45b73161.zip |
We don't use ADNS anymore so get rid of the tree.
Diffstat (limited to 'adns-0.6/src')
-rw-r--r-- | adns-0.6/src/.cvsignore | 2 | ||||
-rw-r--r-- | adns-0.6/src/Makefile.in | 48 | ||||
-rw-r--r-- | adns-0.6/src/adns.h | 818 | ||||
-rw-r--r-- | adns-0.6/src/adns.make | 25 | ||||
-rw-r--r-- | adns-0.6/src/check.c | 199 | ||||
-rw-r--r-- | adns-0.6/src/config.h.in | 91 | ||||
-rw-r--r-- | adns-0.6/src/dlist.h | 53 | ||||
-rw-r--r-- | adns-0.6/src/event.c | 699 | ||||
-rw-r--r-- | adns-0.6/src/general.c | 360 | ||||
-rw-r--r-- | adns-0.6/src/internal.h | 705 | ||||
-rw-r--r-- | adns-0.6/src/parse.c | 253 | ||||
-rw-r--r-- | adns-0.6/src/poll.c | 131 | ||||
-rw-r--r-- | adns-0.6/src/query.c | 540 | ||||
-rw-r--r-- | adns-0.6/src/reply.c | 357 | ||||
-rw-r--r-- | adns-0.6/src/setup.c | 643 | ||||
-rw-r--r-- | adns-0.6/src/transmit.c | 257 | ||||
-rw-r--r-- | adns-0.6/src/tvarith.h | 41 | ||||
-rw-r--r-- | adns-0.6/src/types.c | 1034 |
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; -} |