* - RR-type-specific code, and the machinery to call it
*/
/*
- * This file is part of adns, which is
- * Copyright (C) 1997-2000,2003,2006 Ian Jackson
- * Copyright (C) 1999-2000,2003,2006 Tony Finch
- * Copyright (C) 1991 Massachusetts Institute of Technology
- * (See the file INSTALL for full details.)
+ * This file is part of adns, which is Copyright Ian Jackson
+ * and contributors (see the file INSTALL for full details).
*
* 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)
+ * the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* 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.
+ * along with this program; if not, write to the Free Software Foundation.
*/
#include <stddef.h>
return adns_s_ok;
}
-static adns_status cs_txt(vbuf *vb, const void *datap) {
+static adns_status cs_txt(vbuf *vb, adns_rrtype rrt, const void *datap) {
const adns_rr_intstr *const *rrp= datap;
const adns_rr_intstr *current;
adns_status st;
* _hinfo (cs)
*/
-static adns_status cs_hinfo(vbuf *vb, const void *datap) {
+static adns_status cs_hinfo(vbuf *vb, adns_rrtype rrt, const void *datap) {
const adns_rr_intstrpair *rrp= datap;
adns_status st;
return adns_s_ok;
}
-static adns_status cs_inaddr(vbuf *vb, const void *datap) {
+static adns_status cs_inaddr(vbuf *vb, adns_rrtype rrt, const void *datap) {
return csp_genaddr(vb, AF_INET,datap);
}
return dip_genaddr(ads,AF_INET6,datap_a,datap_b);
}
-static adns_status cs_in6addr(vbuf *vb, const void *datap) {
+static adns_status cs_in6addr(vbuf *vb, adns_rrtype rrt, const void *datap) {
return csp_genaddr(vb,AF_INET6,datap);
}
addr_nrrtypes,
#define RRTY_FLAG(ty) addr_rf_##ty = 1 << addr__ri_##ty,
ADDR_RRTYPES(RRTY_FLAG)
- addr__rrty_hunoz
+ addr__rrty_eat_final_comma
#undef RRTY_FLAG
};
int i;
type &= adns_rrt_typemask;
- for (i=0; i<addr_nrrtypes && type!=addr_all_rrtypes[i]; i++);
- return i < addr_nrrtypes ? 1 << i : 0;
+ for (i=0; i<addr_nrrtypes; i++)
+ if (type==addr_all_rrtypes[i])
+ return 1 << i;
+ return 0;
}
/* About CNAME handling in addr queries.
* adns__qf_addr_cname set so that we know that we're in the fixup state.
*/
-static adns_status pap_addr(const parseinfo *pai, int rrty, size_t rrsz,
- int *cbyte_io, int max, adns_rr_addr *storeto) {
- const byte *dgram= pai->dgram;
- int af, addrlen, salen;
+static adns_status pap_addr(const parseinfo *pai, int in_rrty, size_t out_rrsz,
+ int *cbyte_io, int cbyte_max, adns_rr_addr *out) {
+ int in_addrlen;
+ int out_af, out_salen;
struct in6_addr v6map;
- const void *oaddr= dgram + *cbyte_io;
- int avail= max - *cbyte_io;
- int step= -1;
- void *addrp= 0;
-
- switch (rrty) {
- case adns_r_a:
- if ((pai->qu->flags & adns_qf_ipv6_mapv4) &&
- (pai->qu->answer->type & adns__qtf_bigaddr)) {
- if (avail < 4) return adns_s_invaliddata;
- memset(v6map.s6_addr + 0, 0x00, 10);
- memset(v6map.s6_addr + 10, 0xff, 2);
- memcpy(v6map.s6_addr + 12, oaddr, 4);
- oaddr= v6map.s6_addr; avail= sizeof(v6map.s6_addr);
- if (step < 0) step= 4;
- goto aaaa;
- }
- af= AF_INET; addrlen= 4;
- addrp= &storeto->addr.inet.sin_addr;
- salen= sizeof(storeto->addr.inet);
- break;
- case adns_r_aaaa:
- aaaa:
- af= AF_INET6; addrlen= 16;
- addrp= storeto->addr.inet6.sin6_addr.s6_addr;
- salen= sizeof(storeto->addr.inet6);
- break;
+
+ const void *use_addr= pai->dgram + *cbyte_io;
+
+ switch (in_rrty) {
+ case adns_r_a: in_addrlen= 4; out_af= AF_INET; break;
+ case adns_r_aaaa: in_addrlen= 16; out_af= AF_INET6; break;
+ default: abort();
}
- assert(addrp);
- assert(offsetof(adns_rr_addr, addr) + salen <= rrsz);
- if (addrlen < avail) return adns_s_invaliddata;
- if (step < 0) step= addrlen;
- *cbyte_io += step;
- memset(&storeto->addr, 0, salen);
- storeto->len= salen;
- storeto->addr.sa.sa_family= af;
- memcpy(addrp, oaddr, addrlen);
+ if ((*cbyte_io + in_addrlen) != cbyte_max) return adns_s_invaliddata;
+ if (out_af==AF_INET &&
+ (pai->qu->flags & adns_qf_ipv6_mapv4) &&
+ (pai->qu->answer->type & adns__qtf_bigaddr)) {
+ memset(v6map.s6_addr + 0, 0x00, 10);
+ memset(v6map.s6_addr + 10, 0xff, 2);
+ memcpy(v6map.s6_addr + 12, use_addr, 4);
+ use_addr= v6map.s6_addr;
+ out_af= AF_INET6;
+ }
+
+ switch (out_af) {
+ case AF_INET: out_salen= sizeof(out->addr.inet); break;
+ case AF_INET6: out_salen= sizeof(out->addr.inet6); break;
+ default: abort();
+ }
+
+ assert(offsetof(adns_rr_addr, addr) + out_salen <= out_rrsz);
+
+ memset(&out->addr, 0, out_salen);
+ out->len= out_salen;
+ out->addr.sa.sa_family= out_af;
+ adns__addr_inject(use_addr, &out->addr);
+
+ *cbyte_io += in_addrlen;
return adns_s_ok;
}
return adns_s_ok;
}
-static adns_status cs_addr(vbuf *vb, const void *datap) {
+static adns_status cs_addr(vbuf *vb, adns_rrtype rrt, const void *datap) {
const adns_rr_addr *rrp= datap;
return csp_addr(vb,rrp);
* available record types. The memory management and callback rules are
* the same as for adns__internal_submit.
*
- * Some differences: the query is linked onto the parent's children list
- * before exit (though the parent's state is not changed, and it is not
- * linked into the childw list queue); and we fiddle with the `tinfo'
- * portion of the context structure (yes, modifying *ctx), since this is,
- * in fact, the main purpose of this function.
+ * Some differences: the query is linked onto the parent's children
+ * list before exit (though the parent's state is not changed, and
+ * it is not linked into the childw list queue); and we set the
+ * `tinfo' portion of the context structure (yes, modifying *ctx),
+ * since this is, in fact, the main purpose of this function.
*/
adns_state ads= parent->ads;
struct timeval now;
adns_status err;
adns_queryflags qf;
- int id;
+ int id, r;
propagate_ttl(parent, child);
* settled on.
*/
adns__cancel_children(parent);
- if (gettimeofday(&now, 0)) goto x_gtod;
+ r= adns__gettimeofday(ads,&now); if (r) goto x_gtod;
qf= adns__qf_addr_cname;
if (!(parent->flags & adns_qf_cname_loose)) qf |= adns_qf_cname_forbid;
addr_subqueries(parent, now, qf, child->vb.buf, child->vb.used);
adns__cancel_children(parent);
adns__free_interim(parent, pans->rrs.bytes);
pans->rrs.bytes= 0; pans->nrrs= 0;
- if (gettimeofday(&now, 0)) goto x_gtod;
+ r= adns__gettimeofday(ads,&now); if (r) goto x_gtod;
adns__search_next(ads, parent, now);
return;
}
return;
x_gtod:
- adns__diag(ads, -1, parent, "gettimeofday failed: %s", strerror(errno));
+ /* We have our own error handling, because adns__must_gettimeofday
+ * handles errors by calling adns_globalsystemfailure, which would
+ * reenter the query processing logic. */
+ adns__diag(ads, -1, parent, "gettimeofday/clock_gettime failed: %s",
+ strerror(errno));
err= adns_s_systemfail;
goto x_err;
return adns_s_ok;
}
-static adns_status cs_domain(vbuf *vb, const void *datap) {
+static adns_status cs_domain(vbuf *vb, adns_rrtype rrt, const void *datap) {
const char *const *domainp= datap;
return csp_domain(vb,*domainp);
}
&type, &class, &ttl, &rdlen, &rdstart,
pai->dgram, pai->dglen, dmstart, &ownermatched);
if (st) return st;
+ if (type==-1) continue;
if (!ownermatched || class != DNS_CLASS_IN) continue;
typef= addr_rrtypeflag(type);
if (!(want & typef)) continue;
done:
if (st) {
adns__free_interim(parent, rrp->addrs);
+ rrp->addrs = 0;
rrp->naddrs= (st>0 && st<=adns_s_max_tempfail) ? -1 : 0;
}
mfp_hostaddr(qu,rrp);
}
-static adns_status csp_hostaddr(vbuf *vb, const adns_rr_hostaddr *rrp) {
+static adns_status csp_hostaddr(vbuf *vb, adns_rrtype rrt,
+ const adns_rr_hostaddr *rrp) {
const char *errstr;
adns_status st;
char buf[20];
int i;
+ size_t addrsz= gsz_addr(0, rrt);
st= csp_domain(vb,rrp->host); if (st) return st;
CSP_ADDSTR(" (");
for (i=0; i<rrp->naddrs; i++) {
CSP_ADDSTR(" ");
- st= csp_addr(vb,&rrp->addrs[i]);
+ st= csp_addr(vb, (const void*)((const char*)rrp->addrs + addrsz*i));
}
CSP_ADDSTR(" )");
} else {
return adns_s_ok;
}
-static adns_status cs_hostaddr(vbuf *vb, const void *datap) {
+static adns_status cs_hostaddr(vbuf *vb, adns_rrtype rrt, const void *datap) {
const adns_rr_hostaddr *rrp= datap;
- return csp_hostaddr(vb,rrp);
+ return csp_hostaddr(vb,rrt,rrp);
}
/*
mfp_hostaddr(qu,&rrp->ha);
}
-static adns_status cs_inthostaddr(vbuf *vb, const void *datap) {
- const adns_rr_inthostaddr *rrp= datap;
+static adns_status csp_intofinthost(vbuf *vb, int i) {
char buf[10];
- sprintf(buf,"%u ",rrp->i);
+ if (i < 0 || i > 0xffff)
+ /* currently only used for MX whose priorities are 16-bit */
+ return adns_s_invaliddata;
+
+ sprintf(buf,"%u ",i);
CSP_ADDSTR(buf);
+ return adns_s_ok;
+}
+
+static adns_status cs_inthostaddr(vbuf *vb, adns_rrtype rrt, const void *datap) {
+ const adns_rr_inthostaddr *rrp= datap;
+ adns_status st;
- return csp_hostaddr(vb,&rrp->ha);
+ st = csp_intofinthost(vb,rrp->i); if (st) return st;
+ return csp_hostaddr(vb,rrt,&rrp->ha);
}
/*
* _inthost (cs)
*/
-static adns_status cs_inthost(vbuf *vb, const void *datap) {
+static adns_status cs_inthost(vbuf *vb, adns_rrtype rrt, const void *datap) {
const adns_rr_intstr *rrp= datap;
- char buf[10];
+ adns_status st;
- sprintf(buf,"%u ",rrp->i);
- CSP_ADDSTR(buf);
+ st = csp_intofinthost(vb,rrp->i); if (st) return st;
return csp_domain(vb,rrp->str);
}
pai->dgram, pai->dglen, max,
*cbyte_io, cbyte_io);
st= adns__findlabel_next(&fls,&lablen,&labstart);
+ if (st) return st;
if (!lablen) {
adns__vbuf_appendstr(vb,".");
goto x_ok;
return adns_s_ok;
}
-static adns_status cs_rp(vbuf *vb, const void *datap) {
+static adns_status cs_rp(vbuf *vb, adns_rrtype rrt, const void *datap) {
const adns_rr_strpair *rrp= datap;
adns_status st;
adns_rr_soa *rrp= datap;
const byte *dgram= pai->dgram;
adns_status st;
- int msw, lsw, i;
+ int i;
st= pap_domain(pai, &cbyte, max, &rrp->mname,
pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
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;
+ unsigned long v;
+ (&rrp->serial)[i]= GET_L(cbyte, v);
}
return adns_s_ok;
adns__makefinal_str(qu,&rrp->rname);
}
-static adns_status cs_soa(vbuf *vb, const void *datap) {
+static adns_status cs_soa(vbuf *vb, adns_rrtype rrt, const void *datap) {
const adns_rr_soa *rrp= datap;
char buf[20];
int i;
st= csp_mailbox(vb,rrp->rname); if (st) return st;
for (i=0; i<5; i++) {
+ if (rrp->serial > 0xffffffffUL)
+ return adns_s_invaliddata;
sprintf(buf," %lu",(&rrp->serial)[i]);
CSP_ADDSTR(buf);
}
static adns_status csp_srv_begin(vbuf *vb, const adns_rr_srvha *rrp
/* might be adns_rr_srvraw* */) {
char buf[30];
+ if (rrp->priority < 0 || rrp->priority > 0xffff ||
+ rrp->weight < 0 || rrp->weight > 0xffff ||
+ rrp->port < 0 || rrp->port > 0xffff)
+ return adns_s_invaliddata;
sprintf(buf,"%u %u %u ", rrp->priority, rrp->weight, rrp->port);
CSP_ADDSTR(buf);
return adns_s_ok;
}
-static adns_status cs_srvraw(vbuf *vb, const void *datap) {
+static adns_status cs_srvraw(vbuf *vb, adns_rrtype rrt, const void *datap) {
const adns_rr_srvraw *rrp= datap;
adns_status st;
return csp_domain(vb,rrp->host);
}
-static adns_status cs_srvha(vbuf *vb, const void *datap) {
+static adns_status cs_srvha(vbuf *vb, adns_rrtype rrt, const void *datap) {
const adns_rr_srvha *rrp= datap;
adns_status st;
st= csp_srv_begin(vb,(const void*)datap); if (st) return st;
- return csp_hostaddr(vb,&rrp->ha);
+ return csp_hostaddr(vb,rrt,&rrp->ha);
}
static void postsort_srv(adns_state ads, void *array, int nrrs,int rrsz,
return adns_s_ok;
}
-static adns_status cs_opaque(vbuf *vb, const void *datap) {
+static adns_status cs_opaque(vbuf *vb, adns_rrtype rrt, const void *datap) {
const adns_rr_byteblock *rrp= datap;
char buf[10];
int l;
unsigned char *p;
+ if (rrp->len < 0 || rrp->len > 0xffff)
+ return adns_s_invaliddata;
+
sprintf(buf,"\\# %d",rrp->len);
CSP_ADDSTR(buf);
const typeinfo *adns__findtype(adns_rrtype type) {
const typeinfo *begin, *end, *mid;
+ if (type & ~(adns_rrtype)0x63ffffff)
+ /* 0x60000000 is reserved for `harmless' future expansion */
+ return 0;
+
if (type & adns_r_unknown) return &typeinfo_unknown;
type &= adns_rrt_reprmask;