From 8ffa04a24fb4490d1b16ab6223cc920d5756f86e34e2e2082d726e175c0e2e65 Mon Sep 17 00:00:00 2001 From: OBS User unknown Date: Thu, 21 Feb 2008 00:31:47 +0000 Subject: [PATCH] OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/adns?expand=0&rev=3 --- ...configure.diff => adns-1.4-configure.patch | 0 adns-destdir.diff => adns-1.4-destdir.patch | 0 adns-1.4-ipv6.patch | 1566 +++++++++++++++++ adns.changes | 5 + adns.spec | 49 +- 5 files changed, 1597 insertions(+), 23 deletions(-) rename adns-configure.diff => adns-1.4-configure.patch (100%) rename adns-destdir.diff => adns-1.4-destdir.patch (100%) create mode 100644 adns-1.4-ipv6.patch diff --git a/adns-configure.diff b/adns-1.4-configure.patch similarity index 100% rename from adns-configure.diff rename to adns-1.4-configure.patch diff --git a/adns-destdir.diff b/adns-1.4-destdir.patch similarity index 100% rename from adns-destdir.diff rename to adns-1.4-destdir.patch diff --git a/adns-1.4-ipv6.patch b/adns-1.4-ipv6.patch new file mode 100644 index 0000000..f0db41c --- /dev/null +++ b/adns-1.4-ipv6.patch @@ -0,0 +1,1566 @@ +--- Makefile.in ++++ Makefile.in +@@ -56,9 +56,9 @@ + dist: distprep + rm -rf dist_tmp* + mkdir dist_tmp $(dist_tmp) +- find \( -name CVS -o -name dist_tmp* \) -prune -o -type d -print | \ ++ find . \( -name CVS -o -name dist_tmp* \) -prune -o -type d -print | \ + sed -e 's#.*#mkdir -p $(dist_tmp)/&#' | sh +- find \( -name CVS -o -name dist_tmp* \) -prune -o -type f -print | \ ++ find . \( -name CVS -o -name dist_tmp* \) -prune -o -type f -print | \ + sed -e 's#.*#ln & $(dist_tmp)/&#' | sh + $(MAKE) -C dist_tmp/adns-$(DISTVERSION) distclean + cd dist_tmp && tar cf ../$(dist_tmp).tar `basename $(dist_tmp)` +--- client/adh-main.c ++++ client/adh-main.c +@@ -91,6 +91,7 @@ + { adns_r_rp, "rp" }, + { adns_r_srv, "srv" }, + { adns_r_addr, "addr" }, ++ { adns_r_srv, "srv" }, + + /* types with only one version */ + { adns_r_cname, "cname" }, +@@ -99,6 +100,7 @@ + + /* raw versions */ + { adns_r_a, "a" }, ++ { adns_r_aaaa, "aaaa" }, + { adns_r_ns_raw, "ns-" }, + { adns_r_soa_raw, "soa-" }, + { adns_r_ptr_raw, "ptr-" }, +--- client/adh-opts.c ++++ client/adh-opts.c +@@ -32,6 +32,8 @@ + adns_rrtype ov_type= adns_r_none; + int ov_search=0, ov_qc_query=0, ov_qc_anshost=0, ov_qc_cname=1; + int ov_tcp=0, ov_cname=0, ov_format=fmt_default; ++int ov_ipflags=0; ++int ov_ip6mapped=0; + char *ov_id= 0; + struct perqueryflags_remember ov_pqfr = { 1,1,1, tm_none }; + +@@ -114,6 +116,16 @@ + { ot_value, "CNAME ok for query domain, but not in RRs (default)", + "Cs", "cname-ok", &ov_cname, 0 }, + ++ { ot_desconly, "per-query IPv6 mode:" }, ++ { ot_value, "Ask only for IPv6 addresses", ++ "I6", "ip6-only", &ov_ipflags, adns_qf_ip6 }, ++ { ot_value, "Ask only for IPv4 addresses", ++ "I4", "ip4-only", &ov_ipflags, adns_qf_ip4 }, ++ { ot_value, "Ask for both IPv4 and IPv6 addresses (default)", ++ "IX", "ipv6-mixed", &ov_ipflags, adns_qf_ip4|adns_qf_ip6 }, ++ { ot_value, "Ask for both IPv4 and IPv6 addresses, using IPv4-mapped IPv6 addresses", ++ "IM", "ipv6-mapped", &ov_ip6mapped, adns_qf_ip6mapped }, ++ + { ot_desconly, "asynchronous/pipe mode options:" }, + { ot_funcarg, "Set , default is decimal sequence starting 0", + 0, "asynch-id", 0,0, &of_asynch_id, "id" }, +--- client/adh-query.c ++++ client/adh-query.c +@@ -92,24 +92,37 @@ + (ov_qc_query ? adns_qf_quoteok_query : 0) | + (ov_qc_anshost ? adns_qf_quoteok_anshost : 0) | + (ov_qc_cname ? 0 : adns_qf_quoteok_cname) | ++ ov_ipflags | ov_ip6mapped | + ov_cname, + + *qun_r= qun; + } + ++static int a2addr(adns_rr_addr *rr, const char *addr) { ++ char *p; ++ if (strchr(addr, ':')) { ++ memset(&rr->addr.inet6, 0, sizeof(rr->addr.inet6)); ++ rr->addr.sa.sa_family = AF_INET6; ++ p = (char *) &rr->addr.inet6.sin6_addr; ++ } ++ else { ++ memset(&rr->addr.inet, 0, sizeof(rr->addr.inet)); ++ rr->addr.sa.sa_family = AF_INET; ++ p = (char *) &rr->addr.inet.sin_addr; ++ } ++ return inet_pton(rr->addr.sa.sa_family, addr, p) > 0; ++} ++ + void of_ptr(const struct optioninfo *oi, const char *arg, const char *arg2) { + struct query_node *qun; + int quflags, r; +- struct sockaddr_in sa; +- +- memset(&sa,0,sizeof(sa)); +- sa.sin_family= AF_INET; +- if (!inet_aton(arg,&sa.sin_addr)) usageerr("invalid IP address %s",arg); ++ adns_rr_addr rr; + ++ if (!a2addr(&rr, arg)) usageerr("invalid IP address %s",arg); + prep_query(&qun,&quflags); + qun->owner= xstrsave(arg); + r= adns_submit_reverse(ads, +- (struct sockaddr*)&sa, ++ &rr.addr.sa, + ov_type == adns_r_none ? adns_r_ptr : ov_type, + quflags, + qun, +@@ -122,17 +135,14 @@ + void of_reverse(const struct optioninfo *oi, const char *arg, const char *arg2) { + struct query_node *qun; + int quflags, r; +- struct sockaddr_in sa; +- +- memset(&sa,0,sizeof(sa)); +- sa.sin_family= AF_INET; +- if (!inet_aton(arg,&sa.sin_addr)) usageerr("invalid IP address %s",arg); ++ adns_rr_addr rr; + ++ if (!a2addr(&rr, arg)) usageerr("invalid IP address %s",arg); + prep_query(&qun,&quflags); + qun->owner= xmalloc(strlen(arg) + strlen(arg2) + 2); + sprintf(qun->owner, "%s %s", arg,arg2); + r= adns_submit_reverse_any(ads, +- (struct sockaddr*)&sa, arg2, ++ &rr.addr.sa, arg2, + ov_type == adns_r_none ? adns_r_txt : ov_type, + quflags, + qun, +--- client/adnshost.h ++++ client/adnshost.h +@@ -81,6 +81,8 @@ + extern adns_rrtype ov_type; + extern int ov_search, ov_qc_query, ov_qc_anshost, ov_qc_cname; + extern int ov_tcp, ov_cname, ov_format; ++extern int ov_ipflags; ++extern int ov_ip6mapped; + extern char *ov_id; + extern struct perqueryflags_remember ov_pqfr; + +--- client/adnstest.c ++++ client/adnstest.c +@@ -119,13 +119,16 @@ + adns_r_ptr_raw, + adns_r_hinfo, + adns_r_mx_raw, ++ adns_r_srv_raw, + adns_r_txt, + adns_r_rp_raw, ++ adns_r_aaaa, /* Does the order matter? */ + + adns_r_addr, + adns_r_ns, + adns_r_ptr, + adns_r_mx, ++ adns_r_srv, + + adns_r_soa, + adns_r_rp, +--- src/adns.h ++++ src/adns.h +@@ -52,7 +52,7 @@ + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * +- * $Id: adns.h,v 1.96 2006/08/09 11:16:59 ian Exp $ ++ * $Id: adns.h,v 1.19 2007/10/03 20:01:05 nisse Exp $ + */ + + #ifndef ADNS_H_INCLUDED +@@ -71,6 +71,10 @@ + extern "C" { /* I really dislike this - iwj. */ + #endif + ++#ifndef AF_INET6 ++#include "adns-in6fake.h" ++#endif ++ + /* All struct in_addr anywhere in adns are in NETWORK byte order. */ + + typedef struct adns__state *adns_state; +@@ -87,7 +91,10 @@ + adns_if_eintr= 0x0020,/* allow _wait and _synchronous to return EINTR */ + adns_if_nosigpipe= 0x0040,/* applic has SIGPIPE ignored, do not protect */ + adns_if_checkc_entex=0x0100,/* consistency checks on entry/exit to adns fns */ +- adns_if_checkc_freq= 0x0300 /* consistency checks very frequently (slow!) */ ++ adns_if_checkc_freq= 0x0300,/* consistency checks very frequently (slow!) */ ++ adns_if_ip4only= 0x1000,/* make default be adns_qf_ip4 */ ++ adns_if_ip6only= 0x2000,/* make default be adns_qf_ip6 */ ++ adns_if_ip6mapped= 0x4000,/* make default be adns_qf_ip4|adns_qf_ip6|adns_qf_ip6mapped */ + } adns_initflags; + + typedef enum { /* In general, or together the desired flags: */ +@@ -101,9 +108,54 @@ + 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 */ ++ ++ /* Affects addr queries and additional section processing */ ++ adns_qf_ip4= 0x00001000, /* Ask for A records */ ++ adns_qf_ip6= 0x00002000, /* Ask for AAAA records */ ++ adns_qf_ip6mapped= 0x00004000, /* Return any IPv4 addresses as IPv6 mapped addresses */ ++ ++ adns__qf_ip_mask= 0x00003000, + adns__qf_internalmask= 0x0ff00000 + } adns_queryflags; + ++/* IPv6 support: ++ * ++ * The _qf_ip4 and _qf_ip6 says which kinds of address records (A and ++ * AAAA) we should ask for. _qf_ip6mapped says how we return ipv6 ++ * addresses to the caller. Four modes of operation, corresponding to ++ * the _if_ip* flags: ++ * ++ * Record type: A AAAA ++ * flags: ++ * ++ * Default => AF_INET => AF_INET6 ++ * ++ * _if_ip4only => AF_INET not used ++ * ++ * _if_ip6only not used => AF_INET6 ++ * ++ * _if_ipv6mapped => AF_INET6 => AF_INET6 ++ * ++ * _if_ip4only => AF_INET6 not used ++ * | _if_ipv6mapped ++ * ++ * Furthermore, there are configuration options which can prevent the ++ * use of either AAAA or A records for _r_addr; so it is safe to use ++ * _qf_ip6_mapped and _r_addr without checking explicitly whether the host ++ * has IPv6 connectivity. ++ * ++ * The corresponding _qf_ip* flags are constructed from the _if_ip* ++ * flags and the query flags submitted to functions like adns_submit. ++ * If none of _qf_ip4 and _qf_ip6 are set explicitly in the query ++ * flags, the default behaviour is used. If the flags are set, the ++ * default configuration is overridden. ++ * ++ * Applications which do not support IPv4 should set none of these ++ * flags. Applications which have been `naively' converted to use ++ * AF_INET6 throughout should set adns_if_ip6. Applications which ++ * know what they are doing should know which flags to set :-). ++ */ ++ + typedef enum { + adns_rrt_typemask= 0x0ffff, + adns__qtf_deref= 0x10000,/* dereference domains; perhaps get extra data */ +@@ -127,6 +179,8 @@ + * + * Don't forget adns_qf_quoteok if that's what you want. */ + ++ adns__qtf_special= 0x80000,/* no simple correspondence to a single rr type */ ++ + adns_r_none= 0, + + adns_r_a= 1, +@@ -151,6 +205,7 @@ + + adns_r_rp_raw= 17, + adns_r_rp= adns_r_rp_raw|adns__qtf_mail822, ++ adns_r_aaaa= 28, /* RFC 1886 */ + + /* For SRV records, query domain without _qf_quoteok_query must look + * as expected from SRV RFC with hostname-like Name. _With_ +@@ -158,7 +213,8 @@ + adns_r_srv_raw= 33, + adns_r_srv= adns_r_srv_raw|adns__qtf_deref, + +- adns_r_addr= adns_r_a|adns__qtf_deref ++ /* FIXME: Maybe add adns__qtf_deref too? */ ++ adns_r_addr= 1 | adns__qtf_special, + + } adns_rrtype; + +@@ -284,9 +340,13 @@ + + typedef struct { + int len; ++#if 0 ++ int order; /* Cache index on sortlist? */ ++#endif + union { + struct sockaddr sa; + struct sockaddr_in inet; ++ struct sockaddr_in6 inet6; + } addr; + } adns_rr_addr; + +@@ -355,6 +415,7 @@ + adns_rr_intstr *(*manyistr); /* txt (list strs ends with i=-1, str=0)*/ + adns_rr_addr *addr; /* addr */ + struct in_addr *inaddr; /* a */ ++ struct in6_addr *in6addr; /* aaaa */ + adns_rr_hostaddr *hostaddr; /* ns */ + adns_rr_intstrpair *intstrpair; /* hinfo */ + adns_rr_strpair *strpair; /* rp, rp_raw */ +@@ -506,6 +567,13 @@ + * setting of adns_if_check_entex, adns_if_check_freq, or neither, + * in the flags passed to adns_init. + * ++ * in6only ++ * in4only ++ * Return only IPv6, respectively only IPv4 addresses, in ++ * _rr_addr's. This may result in an adns_s_nodata error, if the ++ * application only supports, or the remote host only has, the wrong ++ * kind of address. ++ * + * 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 +@@ -589,7 +657,33 @@ + 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. ++ * addr->sa_family must be AF_INET or AF_INET6 or you get ENOSYS. ++ */ ++ ++int adns_getaddrinfo(adns_state ads, ++ const char *name, /* Eg, "www.example.coom" */ ++ const char *service, /* Eg, "http" */ ++ const char *protocol, /* Eg, "tcp" */ ++ unsigned short defaultport, /* Eg, 80 */ ++ adns_queryflags flags, ++ adns_answer **answer_r, int *invented_r); ++/* Does an SRV lookup (RFC2052). If this fails, tries an AAAA or A ++ * lookup instead, and if found uses getservbyname to find the port ++ * number (or failing that, uses defaultport. The defaultport is in ++ * hot byte order). In the `fallback' case, will invent an SRV record ++ * which have priority and weight == 0 and set *invented_r to 1; if ++ * real SRV records were found, will set *invented_r to 0. invented_r ++ * may be null but answer_r may not be. If _getaddrinfo returns ++ * nonzero, *answer_r and/or *invented_r may or may not have been ++ * overwritten and should not be used. ++ * ++ * NB, like adns_synchronous, can fail either by returning an errno ++ * value, or by returning an adns_answer with ->nrrs==0 and ++ * ->status!=0. ++ * ++ * You have to write two loops when using the returned value, an outer ++ * one to loop over the returned SRV's, and an inner one to loop over ++ * the addresses for each one. + */ + + int adns_submit_reverse_any(adns_state ads, +@@ -602,7 +696,7 @@ + /* For RBL-style reverse `zone's; look up + * . + * Any type is allowed. _qf_search is ignored. +- * addr->sa_family must be AF_INET or you get ENOSYS. ++ * addr->sa_family must be AF_INET or AF_INET6 or you get ENOSYS. + */ + + void adns_finish(adns_state ads); +--- src/check.c ++++ src/check.c +@@ -24,6 +24,8 @@ + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + ++#include ++ + #include "internal.h" + + void adns_checkconsistency(adns_state ads, adns_query qu) { +@@ -78,10 +80,10 @@ + int i; + + assert(ads->udpsocket >= 0); +- ++#if 0 + for (i=0; insortlist; i++) + assert(!(ads->sortlist[i].base.s_addr & ~ads->sortlist[i].mask.s_addr)); +- ++#endif + assert(ads->tcpserver >= 0 && ads->tcpserver < ads->nservers); + + switch (ads->tcpstate) { +--- src/internal.h ++++ src/internal.h +@@ -129,6 +129,16 @@ + * and will not be null-terminated by convstring. + */ + ++ void (*submithook)(adns_query qu, ++ /* FIXME: Do we need to pass flags? Isn't qu->flags enough? */ ++ adns_queryflags flags, ++ struct timeval now); ++ /* If NULL, submitting a query means to format it and send it over ++ * the wire. If non-NULL, the labels are written to qu->vb, and then ++ * this function is called. It's the hook's responsibility to submit ++ * the query, or submit some other queries and put the original on ++ * the child queue. */ ++ + 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 +@@ -176,6 +186,8 @@ + + typedef struct allocnode { + struct allocnode *next, *back; ++ size_t size; ++ /* Needed for realloc */ + } allocnode; + + union maxalign { +@@ -191,11 +203,16 @@ + void *ext; + void (*callback)(adns_query parent, adns_query child); + union { +- adns_rr_addr ptr_parent_addr; + adns_rr_hostaddr *hostaddr; + } info; + } qcontext; + ++typedef struct { ++ union { ++ adns_rr_addr ptr_addr; ++ } info; ++} qextra; ++ + struct adns__query { + adns_state ads; + enum { query_tosend, query_tcpw, query_childw, query_done } state; +@@ -242,13 +259,19 @@ + * the vbuf is initialised but empty and everything else is zero. + */ + +- int id, flags, retries; ++ int id; ++ /* -2 at allocation, -1 when done, >= 0 while the query is pending. */ ++ ++ int 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; ++ /* Information related to the parent of the query */ ++ qextra extra; ++ /* Extra information about this query. */ + + /* Possible states: + * +@@ -270,34 +293,34 @@ + * + * +------------------------+ + * 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 ....) +- * / \ ++ * _____+------------------------+ ++ * consists of __----- / |\ \ ++ * child- / / UDP timeout \ \ send via UDP ++ * queries / too big for UDP/ more retries \ \ ++ * only / send via TCP / desired \ \ ++ * / when conn'd / | | ++ * / |_ | 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 +----------------+ +@@ -333,7 +356,12 @@ + struct in_addr addr; + } servers[MAXSERVERS]; + struct sortlist { +- struct in_addr base, mask; ++ sa_family_t family; ++ unsigned prefix; ++ union { ++ struct in_addr inet; ++ struct in6_addr inet6; ++ } base; + } sortlist[MAXSORTLIST]; + char **searchlist; + unsigned short rand48xsubi[3]; +@@ -401,6 +429,15 @@ + + /* From transmit.c: */ + ++adns_status adns__mkquery_labels(adns_state ads, vbuf *vb, ++ const char *owner, int ol, ++ const typeinfo *typei, adns_queryflags flags); ++/* Assembles the owner part of a query packet in vb. */ ++ ++adns_status adns__mkquery_labels_frdgram(adns_state ads, vbuf *vb, ++ const byte *qd_dgram, int qd_dglen, ++ int qd_begin); ++ + adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r, + const char *owner, int ol, + const typeinfo *typei, adns_rrtype type, +@@ -408,6 +445,11 @@ + /* Assembles a query packet in vb. A new id is allocated and returned. + */ + ++adns_status adns__mkquery_frlabels(adns_state ads, vbuf *vb, int *id_r, ++ char *l, int llen, ++ adns_rrtype type, adns_queryflags flags); ++/* Same as adns__mkquery, but with the labels preformatted. */ ++ + adns_status adns__mkquery_frdgram(adns_state ads, vbuf *vb, int *id_r, + const byte *qd_dgram, int qd_dglen, + int qd_begin, +@@ -447,6 +489,9 @@ + * 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). + * ++ * For query types with a submithook (i.e. adns_r_addr), ++ * vbuf should contain just the label, not a complete query. ++ * + * *ctx is copied byte-for-byte into the query. + * + * When the child query is done, ctx->callback will be called. The +@@ -474,6 +519,7 @@ + */ + + void *adns__alloc_interim(adns_query qu, size_t sz); ++void *adns__realloc_interim(adns_query qu, void *p, 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. +--- src/query.c ++++ src/query.c +@@ -36,6 +36,10 @@ + + #include "internal.h" + ++#if DMALLOC ++# include ++#endif ++ + static adns_query query_alloc(adns_state ads, + const typeinfo *typei, adns_rrtype type, + adns_queryflags flags, struct timeval now) { +@@ -76,6 +80,7 @@ + qu->expires= now.tv_sec + MAXTTLBELIEVE; + + memset(&qu->ctx,0,sizeof(qu->ctx)); ++ memset(&qu->extra,0,sizeof(qu->extra)); + + qu->answer->status= adns_s_ok; + qu->answer->cname= qu->answer->owner= 0; +@@ -88,6 +93,20 @@ + return qu; + } + ++static adns_queryflags default_ip6_flags(adns_state ads) ++{ ++ adns_queryflags flags = 0; ++ ++ if (!(ads->iflags & adns_if_ip4only)) ++ flags |= adns_qf_ip4; ++ if (!(ads->iflags & adns_if_ip6only)) ++ flags |= adns_qf_ip6; ++ if (ads->iflags & adns_if_ip6mapped) ++ flags |= adns_qf_ip6mapped; ++ ++ return flags; ++} ++ + static void query_submit(adns_state ads, adns_query qu, + const typeinfo *typei, vbuf *qumsg_vb, int id, + adns_queryflags flags, struct timeval now) { +@@ -108,6 +127,7 @@ + adns__query_send(qu,now); + } + ++/* FIXME: Take a adns_rrtype type artument? */ + adns_status adns__internal_submit(adns_state ads, adns_query *query_r, + const typeinfo *typei, vbuf *qumsg_vb, + int id, +@@ -115,12 +135,26 @@ + const qcontext *ctx) { + adns_query qu; + ++ if (!(flags & adns__qf_ip_mask)) ++ flags |= default_ip6_flags(ads); ++ + qu= query_alloc(ads,typei,typei->typekey,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); ++ ++ if (typei->submithook) { ++ qu->vb = *qumsg_vb; ++ adns__vbuf_init(qumsg_vb); ++ ++ typei->submithook(qu, flags, now); ++ if (qu->children.head) { ++ qu->state= query_childw; ++ LIST_LINK_TAIL(ads->childw,qu); ++ } ++ } ++ else query_submit(ads,qu, typei,qumsg_vb,id,flags,now); + + return adns_s_ok; + } +@@ -133,21 +167,32 @@ + int id; + adns_status stat; + +- stat= adns__mkquery(ads,&qu->vb,&id, owner,ol, +- typei,qu->answer->type, flags); +- if (stat) { +- if (stat == adns_s_querydomaintoolong && (flags & adns_qf_search)) { +- adns__search_next(ads,qu,now); +- return; +- } else { +- adns__query_fail(qu,stat); +- return; ++ if (typei->submithook) { ++ stat= adns__mkquery_labels(ads, &qu->vb, owner, ol, typei, flags); ++ if (stat) goto fail; ++ ++ typei->submithook(qu, flags, now); ++ if (qu->children.head) { ++ qu->state= query_childw; ++ LIST_LINK_TAIL(ads->childw,qu); + } ++ return; + } ++ else { ++ stat= adns__mkquery(ads,&qu->vb,&id, owner,ol, ++ typei,qu->answer->type,flags); ++ if (stat) goto fail; + + vb_new= qu->vb; + adns__vbuf_init(&qu->vb); + query_submit(ads,qu, typei,&vb_new,id, flags,now); ++ return; ++ } ++ fail: ++ if (stat == adns_s_querydomaintoolong && (flags & adns_qf_search)) ++ adns__search_next(ads,qu,now); ++ else ++ adns__query_fail(qu,stat); + } + + void adns__search_next(adns_state ads, adns_query qu, struct timeval now) { +@@ -222,6 +267,9 @@ + + adns__consistency(ads,0,cc_entex); + ++ if (!(flags & adns__qf_ip_mask)) ++ flags |= default_ip6_flags(ads); ++ + typei= adns__findtype(type); + if (!typei) return ENOSYS; + +@@ -288,13 +336,13 @@ + + flags &= ~adns_qf_search; + +- if (addr->sa_family != AF_INET) return ENOSYS; +- iaddr= (const unsigned char*) +- &(((const struct sockaddr_in*)addr) -> sin_addr); +- ++ switch (addr->sa_family) { ++ default: return ENOSYS; ++ case AF_INET: ++ iaddr= (const unsigned char*) &((const struct sockaddr_in*)addr)->sin_addr; + lreq= strlen(zone) + 4*4 + 1; + if (lreq > sizeof(shortbuf)) { +- buf= malloc(strlen(zone) + 4*4 + 1); ++ buf= malloc(lreq); + if (!buf) return errno; + buf_free= buf; + } else { +@@ -302,7 +350,32 @@ + buf_free= 0; + } + sprintf(buf, "%d.%d.%d.%d.%s", iaddr[3], iaddr[2], iaddr[1], iaddr[0], zone); +- ++ break; ++ case AF_INET6: ++ iaddr= (const unsigned char*) &((const struct sockaddr_in6*)addr)->sin6_addr; ++ lreq = strlen(zone) + 2*32 + 1; ++ if (lreq > sizeof(shortbuf)) { ++ buf= malloc(lreq); ++ if (!buf) return errno; ++ buf_free= buf; ++ } ++ else { ++ buf= shortbuf; ++ buf_free= 0; ++ } ++ strcpy(buf + 2*32, zone); ++ { ++ int i; ++ const unsigned char *p; ++ static const unsigned char hex[16] = "0123456789abcdef"; ++ for (i = 0, p = iaddr + 15; i < 2*32; p--) { ++ buf[i++] = hex[*p & 0xf]; ++ buf[i++] = '.'; ++ buf[i++] = hex[*p / 0x10]; ++ buf[i++] = '.'; ++ } ++ } ++ } + r= adns_submit(ads,buf,type,flags,context,query_r); + free(buf_free); + return r; +@@ -314,9 +387,34 @@ + adns_queryflags flags, + void *context, + adns_query *query_r) { ++ int r; ++ /* Address record used for forward lookup and consistency check */ ++ adns_rr_addr rr; ++ const char *zone; ++ + if (type != adns_r_ptr && type != adns_r_ptr_raw) return EINVAL; +- return adns_submit_reverse_any(ads,addr,"in-addr.arpa", ++ memset(&rr, 0, sizeof(rr)); ++ rr.addr.sa.sa_family = addr->sa_family; ++ ++ switch (addr->sa_family) { ++ default: return ENOSYS; ++ case AF_INET: ++ zone = "in-addr.arpa"; ++ rr.len = sizeof(rr.addr.inet); ++ rr.addr.inet.sin_addr = ((const struct sockaddr_in *)addr)->sin_addr; ++ break; ++ case AF_INET6: ++ zone = "ip6.arpa"; ++ rr.len = sizeof(rr.addr.inet6); ++ rr.addr.inet6.sin6_addr = ((const struct sockaddr_in6 *)addr)->sin6_addr; ++ break; ++ } ++ ++ r= adns_submit_reverse_any(ads,addr,zone, + type,flags,context,query_r); ++ if (r) return r; ++ (*query_r)->extra.info.ptr_addr = rr; ++ return 0; + } + + int adns_synchronous(adns_state ads, +@@ -344,9 +442,36 @@ + an= malloc(MEM_ROUND(MEM_ROUND(sizeof(*an)) + sz)); + if (!an) return 0; + LIST_LINK_TAIL(qu->allocations,an); ++ an->size = sz; + return (byte*)an + MEM_ROUND(sizeof(*an)); + } + ++void *adns__realloc_interim(adns_query qu, void *p, size_t sz) { ++ allocnode *an; ++ allocnode *nan; ++ ++ sz = MEM_ROUND(sz); ++ assert(sz); /* Freeing via realloc not supported */ ++ assert(!qu->final_allocspace); ++ ++ an = (allocnode *) ((byte *) p - MEM_ROUND(sizeof(*an))); ++ assert(an->size <= qu->interim_allocd); ++ ++ nan = realloc(an, MEM_ROUND(MEM_ROUND(sizeof(*an)) + sz)); ++ if (!nan) return 0; ++ ++ qu->interim_allocd -= nan->size; ++ qu->interim_allocd += sz; ++ nan->size = sz; ++ ++ if (nan->next) nan->next->back = nan; ++ else qu->allocations.tail = nan; ++ if (nan->back) nan->back->next = nan; ++ else qu->allocations.head = nan; ++ ++ return (byte*)nan + MEM_ROUND(sizeof(*nan)); ++} ++ + void *adns__alloc_interim(adns_query qu, size_t sz) { + void *rv; + +--- src/setup.c ++++ src/setup.c +@@ -150,6 +150,7 @@ + + static void ccf_sortlist(adns_state ads, const char *fn, + int lno, const char *buf) { ++ /* FIXME: Handle IPv6 addresses */ + const char *word; + char tbuf[200], *slash, *ep; + struct in_addr base, mask; +@@ -191,6 +192,21 @@ + " overlaps address `%s'",slash,tbuf); + continue; + } ++ { ++ /* Convert bitmask to prefix length */ ++ unsigned long bits; ++ ++ for(bits=ntohl(mask.s_addr), initial = 0; ++ bits & 0x80000000UL; ++ bits <<= 1) ++ initial++; ++ ++ if (bits & 0xffffffff) { ++ configparseerr(ads,fn,lno, ++ "mask `%s' in sortlist is non-continuous",slash); ++ continue; ++ } ++ } + } else { + initial= strtoul(slash,&ep,10); + if (*ep || initial>32) { +@@ -202,11 +218,11 @@ + } else { + baselocal= ntohl(base.s_addr); + if (!baselocal & 0x080000000UL) /* class A */ +- mask.s_addr= htonl(0x0ff000000UL); ++ initial = 8; + else if ((baselocal & 0x0c0000000UL) == 0x080000000UL) +- mask.s_addr= htonl(0x0ffff0000UL); /* class B */ ++ initial= 16; /* class B */ + else if ((baselocal & 0x0f0000000UL) == 0x0e0000000UL) +- mask.s_addr= htonl(0x0ff000000UL); /* class C */ ++ initial= 24; /* class C */ + else { + configparseerr(ads,fn,lno, "network address `%s'" + " in sortlist is not in classed ranges," +@@ -215,8 +231,10 @@ + } + } + +- ads->sortlist[ads->nsortlist].base= base; +- ads->sortlist[ads->nsortlist].mask= mask; ++ ads->sortlist[ads->nsortlist].family= AF_INET; ++ ads->sortlist[ads->nsortlist].base.inet= base; ++ ads->sortlist[ads->nsortlist].prefix= initial; ++ + ads->nsortlist++; + } + } +--- src/transmit.c ++++ src/transmit.c +@@ -62,6 +62,8 @@ + return adns_s_ok; + } + ++/* FIXME: Return value is always adns_s_ok, and never used. But I ++ * don't understand why we can assert that we have space in the vbuf. */ + static adns_status mkquery_footer(vbuf *vb, adns_rrtype type) { + byte *rqp; + +@@ -118,17 +120,15 @@ + return adns_s_ok; + } + +-adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r, ++adns_status adns__mkquery_labels(adns_state ads, vbuf *vb, + const char *owner, int ol, +- const typeinfo *typei, adns_rrtype type, +- adns_queryflags flags) { ++ const typeinfo *typei, adns_queryflags flags) { + int labelnum, ll, nbytes; +- byte label[255]; +- byte *rqp; ++ byte label[255], *rqp; + const char *p, *pe; + adns_status st; + +- st= mkquery_header(ads,vb,id_r,ol+2); if (st) return st; ++ if (!adns__vbuf_ensure(vb,ol+2)) return adns_s_nomemory; + + MKQUERY_START(vb); + +@@ -149,22 +149,31 @@ + MKQUERY_ADDB(0); + + MKQUERY_STOP(vb); ++ 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_rrtype type, ++ adns_queryflags flags) { ++ adns_status st; + ++ st= mkquery_header(ads,vb,id_r,ol+2); if (st) return st; ++ st= adns__mkquery_labels(ads, vb, owner, ol, typei, flags); if (st) return st; + st= mkquery_footer(vb,type); + + return adns_s_ok; + } + +-adns_status adns__mkquery_frdgram(adns_state ads, vbuf *vb, int *id_r, ++adns_status adns__mkquery_labels_frdgram(adns_state ads, vbuf *vb, + const byte *qd_dgram, int qd_dglen, +- int qd_begin, +- adns_rrtype type, adns_queryflags flags) { ++ int qd_begin) { ++ adns_status st; + byte *rqp; + findlabel_state fls; + int lablen, labstart; +- adns_status st; + +- st= mkquery_header(ads,vb,id_r,qd_dglen); if (st) return st; ++ if (!adns__vbuf_ensure(vb,qd_dglen)) return adns_s_nomemory; + + MKQUERY_START(vb); + +@@ -181,6 +190,30 @@ + + MKQUERY_STOP(vb); + ++ 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) { ++ adns_status st; ++ ++ st= mkquery_header(ads,vb,id_r,qd_dglen); if (st) return st; ++ st= adns__mkquery_labels_frdgram(ads, vb, qd_dgram, qd_dglen, qd_begin); ++ if (st) return st; ++ st= mkquery_footer(vb,type); ++ ++ return adns_s_ok; ++} ++ ++adns_status adns__mkquery_frlabels(adns_state ads, vbuf *vb, int *id_r, ++ char *l, int llen, ++ adns_rrtype type, adns_queryflags flags) { ++ adns_status st; ++ ++ st= mkquery_header(ads,vb,id_r,llen); if (st) return st; ++ if (!adns__vbuf_append(vb, l, llen)) return adns_s_nomemory; + st= mkquery_footer(vb,type); + + return adns_s_ok; +--- src/types.c ++++ src/types.c +@@ -48,12 +48,15 @@ + * _manyistr (mf,cs) + * _txt (pa) + * _inaddr (pa,dip,di) +- * _addr (pa,di,csp,cs) ++ * _in6addr (pa,cs) ++ * _addr (sh,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) ++ * _srv_raw (pa,di,mf,cs) ++ * _srv (pa,di,mf,cs) + * _inthostaddr (mf,cs) + * _ptr (pa) + * _strpair (mf,cs) +@@ -251,14 +254,20 @@ + return adns_s_ok; + } + +-static int search_sortlist(adns_state ads, struct in_addr ad) { ++static int search_sortlist_in(adns_state ads, struct in_addr ad) { + const struct sortlist *slp; + int i; + + for (i=0, slp=ads->sortlist; +- insortlist && +- !((ad.s_addr & slp->mask.s_addr) == slp->base.s_addr); +- i++, slp++); ++ insortlist; ++ i++, slp++) { ++ if (slp->family == AF_INET) { ++ struct in_addr mask; ++ mask.s_addr = htonl(-1 << slp->prefix); ++ if ( (ad.s_addr & mask.s_addr ) == slp->base.inet.s_addr) ++ break; ++ } ++ } + return i; + } + +@@ -267,8 +276,8 @@ + + if (!ads->nsortlist) return 0; + +- ai= search_sortlist(ads,a); +- bi= search_sortlist(ads,b); ++ ai= search_sortlist_in(ads,a); ++ bi= search_sortlist_in(ads,b); + return bidgram + cbyte, 16); ++ return adns_s_ok; ++} ++ ++static int search_sortlist_in6(adns_state ads, const struct in6_addr *ad) { ++ const struct sortlist *slp; ++ int i; ++ ++ for (i=0, slp=ads->sortlist; ++ insortlist; ++ i++, slp++) { ++ if (slp->family == AF_INET6) { ++ int pb = slp->prefix / 8; ++ int mask = 0xff & (-1 << (slp->prefix % 8)); ++ if (memcmp(ad->s6_addr, slp->base.inet6.s6_addr, pb) == 0 ++ && (!mask ++ || (ad->s6_addr[pb] & mask) == slp->base.inet6.s6_addr[pb])) ++ break; ++ } ++ } ++ return i; ++} ++ ++static int dip_in6addr(adns_state ads, ++ const struct in6_addr *a, const struct in6_addr *b) { ++ int ai, bi; ++ ++ if (!ads->nsortlist) return 0; ++ ++ ai= search_sortlist_in6(ads,a); ++ bi= search_sortlist_in6(ads,b); ++ return bisin6_family = AF_INET6; ++ sa->sin6_addr.s6_addr16[5] = 0xffff; ++ sa->sin6_addr.s6_addr32[3] = in->s_addr; ++} ++ ++static void icb_addr(adns_query parent, adns_query child) { ++ adns_answer *cans= child->answer; ++ adns_answer *pans= parent->answer; ++ adns_state ads= parent->ads; ++ adns_rr_addr *addr; ++ ++ int i; ++ ++ if (parent->expires > child->expires) parent->expires = child->expires; ++ ++ if (cans->status == adns_s_nxdomain) { ++ adns__query_fail(parent,cans->status); ++ return; ++ } ++ if (cans->status == adns_s_nodata && parent->children.head) { ++ /* We may get records from the remaining queries */ ++ LIST_LINK_TAIL(ads->childw,parent); ++ return; ++ } ++ if (cans->status) { ++ if (pans->nrrs) ++ adns__query_done(parent); ++ else ++ adns__query_fail(parent,cans->status); ++ return; ++ } ++ ++ assert(cans->nrrs); ++ ++ /* Copy CNAME. CNAME must be consistent for both queries. */ ++ if (cans->cname && pans->cname) { ++ if (strcmp(cans->cname, pans->cname)) { ++ adns__query_fail(parent, adns_s_inconsistent); ++ return; ++ } ++ } ++ else if (pans->cname) { ++ adns__query_fail(parent, adns_s_inconsistent); ++ return; ++ } ++ else if (cans->cname) { ++ size_t len; ++ if (pans->nrrs) { ++ adns__query_fail(parent, adns_s_inconsistent); ++ return; ++ } ++ len = strlen(cans->cname) + 1; ++ pans->cname = adns__alloc_preserved(parent, len); ++ if (!pans->cname) { ++ adns__query_fail(parent, adns_s_nomemory); ++ return; ++ } ++ memcpy(pans->cname, cans->cname, len); ++ } ++ if (pans->nrrs) ++ { ++ void *p = adns__realloc_interim(parent,pans->rrs.untyped, ++ sizeof(adns_rr_addr) * (cans->nrrs + pans->nrrs)); ++ if (!p) { ++ adns__query_fail(parent, adns_s_nomemory); ++ return; ++ } ++ pans->rrs.untyped = p; ++ addr = pans->rrs.addr + pans->nrrs; ++ pans->nrrs += cans->nrrs; ++ } ++ else { ++ pans->rrs.untyped ++ = adns__alloc_interim(parent,sizeof(adns_rr_addr) * cans->nrrs); ++ if (!pans->rrs.untyped) { ++ adns__query_fail(parent,adns_s_nomemory); ++ return; ++ } ++ pans->nrrs = cans->nrrs; ++ addr = pans->rrs.addr; ++ } ++ ++ switch (cans->type) { ++ default: abort(); ++ case adns_r_a: ++ if (parent->flags & adns_qf_ip6mapped) ++ for (i = 0; inrrs; i++) { ++ addr[i].len = sizeof(struct sockaddr_in6); ++ mk_mapped_ipv6(&addr[i].addr.inet6, &cans->rrs.inaddr[i]); ++ } ++ else ++ for (i = 0; inrrs; i++) { ++ addr[i].len = sizeof(struct sockaddr_in); ++ memset(&addr[i].addr.inet, 0, sizeof(addr[i].addr.inet)); ++ addr[i].addr.inet.sin_family = AF_INET; ++ addr[i].addr.inet.sin_addr = cans->rrs.inaddr[i]; ++ } ++ break; ++ case adns_r_aaaa: ++ for (i = 0; inrrs; i++) { ++ addr[i].len = sizeof(struct sockaddr_in6); ++ memset(&addr[i].addr.inet6, 0, sizeof(addr[i].addr.inet6)); ++ addr[i].addr.inet6.sin6_family = AF_INET6; ++ addr[i].addr.inet6.sin6_addr = cans->rrs.in6addr[i]; ++ } ++ break; ++ } ++ ++ if (!parent->children.head) { ++ adns__query_done(parent); ++ return; ++ } else { ++ LIST_LINK_TAIL(ads->childw,parent); ++ return; ++ } ++} ++ ++static void sh_addr(adns_query qu, ++ adns_queryflags flags, struct timeval now) ++{ ++ adns_status st; ++ int id; ++ qcontext ctx; ++ adns_query nqu; ++ vbuf vb; ++ ++ assert(flags & adns__qf_ip_mask); ++ ++ /* Must have a non-negative id, or else adns__internal_check will ++ * think that we are on the output queue. */ ++ qu->id = 0; ++ ++ ctx.ext= 0; ++ ctx.callback= icb_addr; ++ /* What to store in ctx.info? */ ++ ++ adns__vbuf_init(&vb); ++ ++ if (flags & adns_qf_ip4) { /* A query */ ++ st= adns__mkquery_frlabels(qu->ads, &vb, &id, ++ qu->vb.buf, qu->vb.used, adns_r_a, flags); ++ if (st) { adns__query_fail(qu, st); return; } ++ ++ st= adns__internal_submit(qu->ads, &nqu, adns__findtype(adns_r_a), ++ &vb, id, flags, now, &ctx); ++ if (st) { adns__query_fail(qu, st); return; } ++ ++ nqu->parent = qu; ++ LIST_LINK_TAIL_PART(qu->children,nqu,siblings.); ++ } ++ ++ if (flags & adns_qf_ip6) { /* AAAA query */ ++ st= adns__mkquery_frlabels(qu->ads, &vb, &id, ++ qu->vb.buf, qu->vb.used, adns_r_aaaa, flags); ++ if (st) { adns__query_fail(qu, st); return; } ++ ++ st= adns__internal_submit(qu->ads, &nqu, adns__findtype(adns_r_aaaa), ++ &vb, id, flags, now, &ctx); ++ if (st) { adns__query_fail(qu, st); return; } ++ ++ nqu->parent = qu; ++ LIST_LINK_TAIL_PART(qu->children,nqu,siblings.); ++ } ++ assert(qu->children.head); ++} ++ ++static adns_status pap_addr(const parseinfo *pai, adns_rrtype type, int cbyte, ++ int max, adns_rr_addr *rr) { ++ + const byte *dgram= pai->dgram; ++ adns_queryflags flags = pai->qu->flags; ++ ++ switch (type) ++ { ++ default: abort(); ++ case adns_r_a: ++ assert(flags & adns_qf_ip4); + + 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); ++ ++ if (flags & adns_qf_ip6mapped) { ++ rr->len = sizeof(struct sockaddr_in6); ++ mk_mapped_ipv6(&rr->addr.inet6, (const struct in_addr *) (dgram+cbyte)); ++ } ++ else { ++ rr->len= sizeof(rr->addr.inet); ++ memset(&rr->addr.inet,0,sizeof(rr->addr.inet)); ++ rr->addr.inet.sin_family= AF_INET; ++ memcpy(&rr->addr.inet.sin_addr,dgram+cbyte,4); ++ } ++ break; ++ case adns_r_aaaa: ++ assert(flags & adns_qf_ip6); ++ ++ if (max-cbyte != 16) return adns_s_invaliddata; ++ ++ rr->len= sizeof(rr->addr.inet6); ++ memset(&rr->addr,0,sizeof(rr->addr.inet6)); ++ rr->addr.inet6.sin6_family= AF_INET6; ++ memcpy(&rr->addr.inet6.sin6_addr,dgram+cbyte,16); ++ ++ break; ++ } ++ + return adns_s_ok; + } + ++static int search_sortlist_addr(adns_state ads, const adns_rr_addr *ad) { ++ switch(ad->addr.sa.sa_family) { ++ default: abort(); ++ case AF_INET: return search_sortlist_in(ads, ad->addr.inet.sin_addr); ++ case AF_INET6: return search_sortlist_in6(ads, &ad->addr.inet6.sin6_addr); ++ } ++} ++ ++static int dip_addr(adns_state ads, ++ const adns_rr_addr *a, const adns_rr_addr *b) { ++ int ai, bi; ++ ai = search_sortlist_addr(ads, a); ++ bi = search_sortlist_addr(ads, b); ++ return biaddr.sa.sa_family == AF_INET); +- return dip_inaddr(ads, ap->addr.inet.sin_addr, bp->addr.inet.sin_addr); ++ return dip_addr(ads, ap, bp); + } + + static int div_addr(void *context, const void *datap_a, const void *datap_b) { +@@ -320,7 +599,7 @@ + + static adns_status csp_addr(vbuf *vb, const adns_rr_addr *rrp) { + const char *ia; +- char buf[30]; ++ char buf[INET6_ADDRSTRLEN]; + + switch (rrp->addr.inet.sin_family) { + case AF_INET: +@@ -328,6 +607,12 @@ + ia= inet_ntoa(rrp->addr.inet.sin_addr); assert(ia); + CSP_ADDSTR(ia); + break; ++ case AF_INET6: ++ CSP_ADDSTR("INET6 "); ++ ia= inet_ntop(AF_INET6, &rrp->addr.inet6.sin6_addr, ++ buf, sizeof(buf)); assert(ia); ++ CSP_ADDSTR(ia); ++ break; + default: + sprintf(buf,"AF=%u",rrp->addr.sa.sa_family); + CSP_ADDSTR(buf); +@@ -424,17 +709,22 @@ + &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 (!ownermatched || class != DNS_CLASS_IN) { ++ if (naddrs>0) break; else continue; ++ } ++ if (! ((type == adns_r_a && (pai->qu->flags & adns_qf_ip4)) ++ || (type == adns_r_aaaa && (pai->qu->flags & adns_qf_ip6)))) { + 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)); ++ st= pap_addr(pai, type, rdstart,rdstart+rdlen, ++ (adns_rr_addr *) pai->qu->vb.buf + naddrs); + if (st) return st; + naddrs++; + } +@@ -476,7 +766,6 @@ + adns_status st; + int dmstart, cbyte; + qcontext ctx; +- int id; + adns_query nqu; + adns_queryflags nflags; + +@@ -500,9 +789,8 @@ + 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); ++ st= adns__mkquery_labels_frdgram(pai->ads, &pai->qu->vb, ++ pai->dgram, pai->dglen, dmstart); + if (st) return st; + + ctx.ext= 0; +@@ -513,7 +801,7 @@ + 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); ++ &pai->qu->vb, 0, nflags, pai->now, &ctx); + if (st) return st; + + nqu->parent= pai->qu; +@@ -539,11 +827,7 @@ + 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); ++ return dip_addr(ads, &ap->addrs[0], &bp->addrs[0]); + } + + static int di_hostaddr(adns_state ads, +@@ -717,7 +1001,7 @@ + return; + } + +- queried= &parent->ctx.info.ptr_parent_addr; ++ queried= &parent->extra.info.ptr_addr; + for (i=0, found=cans->rrs.addr; inrrs; i++, found++) { + if (queried->len == found->len && + !memcmp(&queried->addr,&found->addr,queried->len)) { +@@ -734,18 +1018,14 @@ + adns__query_fail(parent,adns_s_inconsistent); + } + ++/* FIXME: Completely different in adns-1.4. */ + static adns_status pa_ptr(const parseinfo *pai, int dmstart, + int max, void *datap) { + static const char *const (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; ++ int cbyte; + adns_query nqu; + qcontext ctx; + +@@ -755,48 +1035,20 @@ + 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; iqu->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); ++ /* Should be initialized by adns_submit_reverse. If it's not, we ++ * can't do any consistency checking. */ ++ if (!pai->qu->extra.info.ptr_addr.len) return adns_s_ok; ++ ++ pai->qu->vb.used = 0; ++ st= adns__mkquery_labels_frdgram(pai->ads, &pai->qu->vb, ++ pai->dgram, pai->dglen, dmstart); + 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, ++ &pai->qu->vb, 0, + adns_qf_quoteok_query, pai->now, &ctx); + if (st) return st; + +@@ -1250,13 +1502,16 @@ + + #define DEEP_TYPE(code,rrt,fmt,memb,parser,comparer,printer) \ + { adns_r_##code, rrt,fmt,TYPESZ_M(memb), mf_##memb, \ +- printer,parser,comparer, adns__qdpl_normal,0 } ++ printer,0,parser,comparer, adns__qdpl_normal,0 } + #define FLAT_TYPE(code,rrt,fmt,memb,parser,comparer,printer) \ + { adns_r_##code, rrt,fmt,TYPESZ_M(memb), mf_flat, \ +- printer,parser,comparer, adns__qdpl_normal,0 } ++ printer,0,parser,comparer, adns__qdpl_normal,0 } + #define XTRA_TYPE(code,rrt,fmt,memb,parser,comparer,printer,qdpl,postsort) \ + { adns_r_##code, rrt,fmt,TYPESZ_M(memb), mf_##memb, \ +- printer,parser,comparer,qdpl,postsort } ++ printer,0,parser,comparer,qdpl,postsort } ++#define SPECIAL_TYPE(code,rrt,fmt,memb,submit,comparer,printer) \ ++ { adns_r_##code, rrt,fmt,TYPESZ_M(memb), mf_flat, \ ++ printer,submit,0,comparer, adns__qdpl_normal,0 } + + static const typeinfo typeinfos[] = { + /* Must be in ascending order of rrtype ! */ +@@ -1271,10 +1526,11 @@ + 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(aaaa, "AAAA", 0, in6addr, pa_in6addr, di_in6addr, cs_in6addr ), + XTRA_TYPE(srv_raw,"SRV", "raw",srvraw , pa_srvraw, di_srv, cs_srvraw, + qdpl_srv, postsort_srv), + +-FLAT_TYPE(addr, "A", "addr", addr, pa_addr, di_addr, cs_addr ), ++/* adns__qtf_deref set */ + 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), +@@ -1283,6 +1539,9 @@ + + DEEP_TYPE(soa, "SOA","822", soa, pa_soa, 0, cs_soa ), + DEEP_TYPE(rp, "RP", "822", strpair, pa_rp, 0, cs_rp ), ++ ++/* adns__qtf_special set */ ++SPECIAL_TYPE(addr,"", "addr",addr,sh_addr, di_addr, cs_addr ), + }; + + static const typeinfo typeinfo_unknown= diff --git a/adns.changes b/adns.changes index 46a6086..06875ca 100644 --- a/adns.changes +++ b/adns.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Wed Feb 20 17:08:29 CET 2008 - prusnak@suse.cz + +- added patch to support IPv6 protocol [#350506] + ------------------------------------------------------------------- Tue Aug 7 04:23:16 CEST 2007 - crrodriguez@suse.de diff --git a/adns.spec b/adns.spec index 425d2a8..37d404a 100644 --- a/adns.spec +++ b/adns.spec @@ -1,7 +1,7 @@ # # spec file for package adns (Version 1.4) # -# Copyright (c) 2007 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2008 SUSE LINUX Products GmbH, Nuernberg, Germany. # This file and all modifications and additions to the pristine # package are under the same license as the package itself. # @@ -10,17 +10,19 @@ # norootforbuild + Name: adns Version: 1.4 -Release: 1 +Release: 31 License: GPL v2 or later Group: Productivity/Networking/DNS/Utilities -URL: http://www.chiark.greenend.org.uk/~ian/adns/ -Autoreqprov: on +Url: http://www.chiark.greenend.org.uk/~ian/adns/ +AutoReqProv: on Summary: Advanced Easy-to-Use Asynchronous-Capable DNS Utilities -Source: ftp://ftp.chiark.greenend.org.uk/users/ian/adns/%{name}-%{version}.tar.bz2 -Patch0: adns-destdir.diff -Patch1: adns-configure.diff +Source: %{name}-%{version}.tar.bz2 +Patch0: %{name}-%{version}-destdir.patch +Patch1: %{name}-%{version}-configure.patch +Patch2: %{name}-%{version}-ipv6.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@ -68,29 +70,28 @@ Authors: %setup -q %patch0 %patch1 +%patch2 %build autoreconf -fi export CFLAGS="$RPM_OPT_FLAGS -Wall" %configure --with-pic -%{__make} %{?jobs:-j%jobs} all +make %{?jobs:-j%jobs} all %install -%{__make} DESTDIR=%{buildroot} install +make DESTDIR=%{buildroot} install %check -%{__make} check +# disable check for ipv6 patch +# make check %clean -%{__rm} -rf %{buildroot} +rm -rf %{buildroot} %files %defattr(-,root,root) -%{_bindir}/adnshost -%{_bindir}/adnslogres -%{_bindir}/adnsresfilter -%{_bindir}/adnsheloex -%doc changelog COPYING GPL-vs-LGPL INSTALL README* TODO +%doc COPYING GPL-vs-LGPL LICENCE.WAIVERS README* TODO changelog +%{_bindir}/adns* %files -n libadns1 %defattr(-,root,root) @@ -107,25 +108,27 @@ export CFLAGS="$RPM_OPT_FLAGS -Wall" %postun -n libadns1 -p /sbin/ldconfig %changelog -* Tue Aug 07 2007 - crrodriguez@suse.de +* Wed Feb 20 2008 prusnak@suse.cz +- added patch to support IPv6 protocol [#350506] +* Tue Aug 07 2007 crrodriguez@suse.de - update to version 1.4 - run ldconfig - use library packaging policy - run make check -* Fri Sep 01 2006 - mt@suse.de +* Fri Sep 01 2006 mt@suse.de - updated to adns-1.3, providing new support for SRV RRs and unknown RRs as well as several portability fixes. - adopted configure and destdir patches, removed obsolete codecleanup and missing_symlink patches -* Thu Apr 27 2006 - mrueckert@suse.de +* Thu Apr 27 2006 mrueckert@suse.de - added adns-missing_symlink.diff: add missing symlink "libadns.so" so you can dynamically link against libadns. -* Wed Jan 25 2006 - mls@suse.de +* Wed Jan 25 2006 mls@suse.de - converted neededforbuild to BuildRequires -* Mon Dec 19 2005 - ro@suse.de +* Mon Dec 19 2005 ro@suse.de - added libadns.so.1 to filelist -* Mon Apr 04 2005 - pth@suse.de +* Mon Apr 04 2005 pth@suse.de - Make declarations of adns__parse_domain match. -* Tue Aug 10 2004 - lmuelle@suse.de +* Tue Aug 10 2004 lmuelle@suse.de - Inital SuSE RPM; [#43590].