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_noautosys= 0x0010, /* do not make syscalls at every opportunity */
- adns_if_eintr= 0x0020, /* allow _wait and _synchronous to return EINTR */
+ 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_noautosys= 0x0010, /* do not make syscalls at every opportunity */
+ adns_if_eintr= 0x0020, /* allow _wait and _synchronous to return EINTR */
+
+ /* Flags for address formatting, in both init and query. Do not use directly. */
+ adns__iqaf_keepv4= 0x01000, /* If clear, any IPv4s will be mapped to AF_INET6 */
+ adns__iqaf_weakv6= 0x02000, /* `Prefer IPv6 less' - depends on other flags */
+ adns__iqaf_only= 0x04000, /* Return only one kind of address */
+ adns__iqaf_override= 0x08000, /* In query flags, means to ignore init flags */
+ adns__iqaf_mask= 0x07000, /* Mask of flags that _override overrides */
+
+ /* Actual address formatting options. These set the default. Do not combine them.
+ * Meanings are:
+ * _v6first: Query for AAAA; if no AAAA then query for A. Return all as AF_INET6.
+ * _v6first: Same, but return IPv6 as AF_INET6 and IPv4 as AF_INET.
+ * _both: Query for both A and AAAA, return all addresses as AF_INET6.
+ * _bothraw: Same, but return IPv6 as AF_INET6 and IPv4 as AF_INET.
+ * _v4only: Query only for A, and return as AF_INET.
+ * _v6only: Query only for AAAA, and return as AF_INET6.
+ * If none is specified, the default is _v6first.
+ */
+ adns_if_addr_v6first= 0,
+ adns_if_addr_v6firstraw= adns__iqaf_keepv4,
+ adns_if_addr_both= adns__iqaf_weakv6,
+ adns_if_addr_bothraw= adns__iqaf_weakv6|adns__iqaf_keepv4,
+ adns_if_addr_v4only= adns__iqaf_only|adns__iqaf_weakv6|adns__iqaf_keepv4,
+ adns_if_addr_v6only= adns__iqaf_only,
+
+ adns__if_internalmask= 0x7fff0000
} adns_initflags;
typedef enum {
- adns_qf_search= 0x000001, /* use the searchlist */
- adns_qf_usevc= 0x000002, /* use a virtual circuit (TCP connection) */
- adns_qf_quoteok_query= 0x000010, /* allow quote-requiring chars in query domain */
- adns_qf_quoteok_cname= 0x000020, /* allow ... in CNAME we go via */
- adns_qf_quoteok_anshost= 0x000040, /* allow ... in answers expected to be hostnames */
- adns_qf_cname_loose= 0x000100, /* allow refs to CNAMEs - without, get _s_cname */
- adns_qf_cname_forbid= 0x000200, /* don't follow CNAMEs, instead give _s_cname */
- adns__qf_internalmask= 0x0ff000
+ adns_qf_search= 0x0000001, /* use the searchlist */
+ adns_qf_usevc= 0x0000002, /* use a virtual circuit (TCP connection) */
+ adns_qf_quoteok_query= 0x0000010, /* allow quote-requiring chars in query domain */
+ adns_qf_quoteok_cname= 0x0000020, /* allow ... in CNAME we go via */
+ adns_qf_quoteok_anshost= 0x0000040, /* allow ... in answers expected to be hostnames */
+ adns_qf_cname_loose= 0x0000100, /* allow refs to CNAMEs - without, get _s_cname */
+ adns_qf_cname_forbid= 0x0000200, /* don't follow CNAMEs, instead give _s_cname */
+
+ /* Address formatting options. They have the same meaning as the corresponding
+ * adns_if_... options. Do not combine with other _if_addr/_qf_addr options.
+ * If a _qf_addr is specified then the _if_addr are irrelevant, otherwise the
+ * _if_addr are used.
+ */
+ adns_qf_addr_both= adns__iqaf_override|adns_if_addr_both,
+ adns_qf_addr_bothraw= adns__iqaf_override|adns_if_addr_bothraw,
+ adns_qf_addr_v6first= adns__iqaf_override|adns_if_addr_v6first,
+ adns_qf_addr_v6firstraw= adns__iqaf_override|adns_if_addr_v6firstraw,
+ adns_qf_addr_v4only= adns__iqaf_override|adns_if_addr_v4only,
+ adns_qf_addr_v6only= adns__iqaf_override|adns_if_addr_v6only,
+
+ adns__qf_internalmask= 0x7fff0000
} 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__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__qtf_nostdquery= 0x40000, /* do not make normal initial query */
+ adns__qtf_mask= 0x07fff0000,
adns_r_none= 0,
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_r_aaaa= 28,
+
+ adns_r_addr= adns_r_a|adns__qtf_nostdquery
} adns_rrtype;
int len;
union {
struct sockaddr sa;
- struct sockaddr_in inet;
+ struct sockaddr_in inet; /* port field will be zero */
+ struct sockaddr_in6 inet6; /* port field will be zero */
} addr;
} adns_rr_addr;
adns_rr_intstr *(*manyistr); /* txt (list of strings ends with i=-1, str=0) */
adns_rr_addr *addr; /* addr */
struct in_addr *inaddr; /* a */
+ struct in_addr6 *inaddr6; /* aaaa */
adns_rr_hostaddr *hostaddr; /* ns */
adns_rr_intstrpair *intstrpair; /* hinfo */
adns_rr_strpair *strpair; /* rp, rp_raw */
adns_answer **answer_r,
void **context_r);
/* fixme: include TTL in answer somehow */
-/* fixme: multithreading/locking */
/* fixme: easy way to get lists of fd's */
/* fixme: IPv6 */
}
/*
- * _addr (pa,di,csp,cs)
+ * _inaddr6 (pa,dip,di)
+ */
+
+static adns_status pa_inaddr6(const parseinfo *pai, int cbyte, int max, void *datap) {
+ struct in_addr6 *storeto= datap;
+
+ if (max-cbyte != 16) return adns_s_invaliddata;
+ memcpy(storeto, pai->dgram + cbyte, 16);
+ return adns_s_ok;
+}
+
+static int dip_inaddr6(adns_state ads, struct in_addr a, struct in_addr b) {
+ return 0;
+}
+
+static int di_inaddr6(adns_state ads, const void *datap_a, const void *datap_b) {
+ const struct in_addr6 *ap= datap_a, *bp= datap_b;
+
+ return dip_inaddr6(ads,*ap,*bp);
+}
+
+static adns_status cs_inaddr6(vbuf *vb, const void *datap) {
+ char buf[INET6_ADDRSTRLEN], *ia;
+
+ ia= inet_ntop(AF_INET6,datap,buf,sizeof(buf); assert(ia);
+ CSP_ADDSTR(ia);
+ return adns_s_ok;
+}
+
+/*
+ * _addr (pa,di,csp,cs, iq,bg)
*/
static adns_status pa_addr(const parseinfo *pai, int cbyte, int max, void *datap) {
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);
+ switch (ap->addr.sa.sa_family) {
+ case AF_INET6:
+ switch (bp->addr.sa.sa_family) {
+ case AF_INET6:
+ return dip_inaddr6(ads, ap->addr.inet6.sin_addr, bp->addr.inet6.sin_addr);
+ case AF_INET:
+ return 0;
+ }
+ break;
+ case AF_INET:
+ switch (bp->addr.sa.sa_family) {
+ case AF_INET:
+ return dip_inaddr(ads, ap->addr.inet.sin_addr, bp->addr.inet.sin_addr);
+ case AF_INET6:
+ return 1;
+ }
+ break;
+ }
+ abort();
}
static int div_addr(void *context, const void *datap_a, const void *datap_b) {
static adns_status csp_addr(vbuf *vb, const adns_rr_addr *rrp) {
const char *ia;
- static char buf[30];
+ static char buf[INET6_ADDRSTRLEN];
switch (rrp->addr.inet.sin_family) {
case AF_INET:
CSP_ADDSTR("AF_INET ");
- ia= inet_ntoa(rrp->addr.inet.sin_addr); assert(ia);
+ ia= inet_ntoa(rrp->addr.inet.sin_addr);
+ assert(ia);
+ CSP_ADDSTR(ia);
+ break;
+ case AF_INET6:
+ if (IN6_IS_ADDR_V4MAPPED(&rrp->addr.inet6.sin6_addr)) {
+ CSP_ADDSTR("IPv6-mapped-IPv4 ");
+ ia= inet_ntoa(*(struct in_addr*)(rrp->addr.inet6.sin6_addr.s6_addr+12));
+ assert(ia);
+ } else {
+ CSP_ADDSTR("AF_INET6 ");
+ ia= inet_ntop(AF_INET6,&rrp->addr.inet.sin6_addr,buf,sizeof(buf));
+ assert(ia);
+ }
CSP_ADDSTR(ia);
break;
default:
return csp_addr(vb,rrp);
}
+static int iq_addr(adns_state ads, adns_queryflags flags) {
+ if (~flags & (adns__iqaf_only|adns__iqaf_weakv6)) {
+ return adns_rr_aaaa;
+ } else {
+ return adns_rr_a;
+ }
+}
+
+static adns_status bg_addr(adns_state ads, adns_query qu, struct timeval now) {
+ qcontext ctx;
+
+ if (!((flags^adns__iqaf_weakv6) & (adns__iqaf_weakv6|adns__iqaf_only))) {
+ ctx.ext= 0;
+ ctx.callback= icb_addr4;
+
+ st= adns__subquery(ads, qu, qu->vb,
+ qu->query_dgram, query_dglen, DNS_HDRSIZE,
+ adns_rr_a, qu->flags, now, &ctx);
+ if (!st) return st;
+ }
+ adns__query_udp(qu,now);
+
+ return adns_s_ok;
+}
+
/*
* _domain (pap)
*/
int max, adns_rr_hostaddr *rrp) {
adns_status st;
int dmstart, cbyte;
- qcontext ctx;
- int id;
- adns_query nqu;
adns_queryflags nflags;
+ qcontext ctx;
dmstart= cbyte= *cbyte_io;
st= pap_domain(pai, &cbyte, max, &rrp->host,
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;
+
+ nflags= adns_qf_quoteok_query;
+ if (!(pai->qu->flags & adns_qf_cname_loose)) nflags |= adns_qf_cname_forbid;
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, 0, &ctx);
- if (st) return st;
- nqu->parent= pai->qu;
- LIST_LINK_TAIL_PART(pai->qu->children,nqu,siblings.);
+ st= adns__subquery(pai->ads, pai->qu, pai->qu->vb,
+ pai->dgram, pai->dglen, dmstart,
+ adns_r_addr, nflags, now, &ctx);
+ if (st) return st;
return adns_s_ok;
}
#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 ANY_TYPE(code,rrt,fmt,memb,makefinal,parser,comparer, initqcode,begin) \
+ { adns_r_##code, rrt, fmt, TYPESZ_M(memb), makefinal, cs_##memb, parser, comparer, \
+ initqcode, begin }
#define DEEP_TYPE(code,rrt,fmt,memb,parser,comparer) \
- { adns_r_##code, rrt, fmt, TYPESZ_M(memb), mf_##memb, cs_##memb, parser, comparer }
+ ANY_TYPE(code,rrt,fmt,memb, mf_##memb,parser,comparer, 0,0)
#define FLAT_TYPE(code,rrt,fmt,memb,parser,comparer) \
- { adns_r_##code, rrt, fmt, TYPESZ_M(memb), mf_flat, cs_##memb, parser, comparer }
+ ANY_TYPE(code,rrt,fmt,memb, mf_flat,parser,comparer, 0,0)
+
+#define DEEP_SPEC(code,rrt,fmt,memb,parser,comparer) \
+ ANY_TYPE(code,rrt,fmt,memb, mf_##memb,parser,comparer, iq_##memb,bg_##memb)
+#define FLAT_SPEC(code,rrt,fmt,memb,parser,comparer) \
+ ANY_TYPE(code,rrt,fmt,memb, mf_flat,parser,comparer, iq_##memb,bg_##memb)
static const typeinfo typeinfos[] = {
-/* Must be in ascending order of rrtype ! */
-/* mem-mgmt code rrt fmt member parser comparer */
-
- FLAT_TYPE(a, "A", 0, inaddr, pa_inaddr, di_inaddr ),
- DEEP_TYPE(ns_raw, "NS", "raw", str, pa_host_raw, 0 ),
- DEEP_TYPE(cname, "CNAME", 0, str, pa_host_raw, 0 ),
- DEEP_TYPE(soa_raw, "SOA", "raw", soa, pa_soa, 0 ),
- DEEP_TYPE(ptr_raw, "PTR", "raw", str, pa_host_raw, 0 ),
- DEEP_TYPE(hinfo, "HINFO", 0, intstrpair, pa_hinfo, 0 ),
- DEEP_TYPE(mx_raw, "MX", "raw", intstr, pa_mx_raw, di_mx_raw ),
- DEEP_TYPE(txt, "TXT", 0, manyistr, pa_txt, 0 ),
- DEEP_TYPE(rp_raw, "RP", "raw", strpair, pa_rp, 0 ),
-
- FLAT_TYPE(addr, "A", "addr", addr, pa_addr, di_addr ),
- DEEP_TYPE(ns, "NS", "+addr", hostaddr, pa_hostaddr, di_hostaddr ),
- DEEP_TYPE(ptr, "PTR","checked", str, pa_ptr, 0 ),
- DEEP_TYPE(mx, "MX", "+addr", inthostaddr, pa_mx, di_mx ),
-
- DEEP_TYPE(soa, "SOA","822", soa, pa_soa, 0 ),
- DEEP_TYPE(rp, "RP", "822", strpair, pa_rp, 0 ),
+/* Must be in ascending order of code ! */
+/* mem-mgmt code rrt fmt member parser comparer */
+
+ FLAT_TYPE(a, "A", 0, inaddr, pa_inaddr, di_inaddr ),
+ DEEP_TYPE(ns_raw, "NS", "raw", str, pa_host_raw, 0 ),
+ DEEP_TYPE(cname, "CNAME", 0, str, pa_host_raw, 0 ),
+ DEEP_TYPE(soa_raw, "SOA", "raw", soa, pa_soa, 0 ),
+ DEEP_TYPE(ptr_raw, "PTR", "raw", str, pa_host_raw, 0 ),
+ DEEP_TYPE(hinfo, "HINFO", 0, intstrpair, pa_hinfo, 0 ),
+ DEEP_TYPE(mx_raw, "MX", "raw", intstr, pa_mx_raw, di_mx_raw ),
+ DEEP_TYPE(txt, "TXT", 0, manyistr, pa_txt, 0 ),
+ DEEP_TYPE(rp_raw, "RP", "raw", strpair, pa_rp, 0 ),
+ FLAT_TYPE(aaaa, "AAAA", 0, inaddr6, pa_inaddr6, di_inaddr6 ),
+
+ FLAT_SPEC(addr, "addr", 0, addr, pa_addr, di_addr ),
+ DEEP_TYPE(ns, "NS", "+addr", hostaddr, pa_hostaddr, di_hostaddr ),
+ DEEP_TYPE(ptr, "PTR", "checked", str, pa_ptr, 0 ),
+ DEEP_TYPE(mx, "MX", "+addr", inthostaddr, pa_mx, di_mx ),
+
+ DEEP_TYPE(soa, "SOA", "822", soa, pa_soa, 0 ),
+ DEEP_TYPE(rp, "RP", "822", strpair, pa_rp, 0 ),
};
const typeinfo *adns__findtype(adns_rrtype type) {