We must track which records have been returned explicitly, because we
don't want to resubmit queries which returned NODATA unnecessarily.
This lopens up the possibility of not cancelling the previous
outstanding queries, and taking their results if they're consistent with
our chosen CNAME, but I'm not doing that yet.
#define DNS_INADDR_ARPA "in-addr", "arpa"
#define DNS_IP6_ARPA "ip6", "arpa"
#define DNS_INADDR_ARPA "in-addr", "arpa"
#define DNS_IP6_ARPA "ip6", "arpa"
+#define ADDR_MAXRRTYPES 2
+
#define STRINGIFY(x) REALLY_STRINGIFY(x)
#define REALLY_STRINGIFY(x) #x
#define STRINGIFY(x) REALLY_STRINGIFY(x)
#define REALLY_STRINGIFY(x) #x
struct timeval timeout;
time_t expires; /* Earliest expiry time of any record we used. */
struct timeval timeout;
time_t expires; /* Earliest expiry time of any record we used. */
+ union {
+ struct {
+ size_t nrrty, onrrty;
+ adns_rrtype rrty[ADDR_MAXRRTYPES];
+ } addr;
+ } t; /* type-specific state */
+
qcontext ctx;
/* Possible states:
qcontext ctx;
/* Possible states:
return csp_addr(vb,rrp);
}
return csp_addr(vb,rrp);
}
-#define ADDR_MAXRRTYPES 2
-
static void addr_rrtypes(adns_state ads, adns_rrtype type,
adns_queryflags qf,
adns_rrtype *rrty, size_t *nrrty)
static void addr_rrtypes(adns_state ads, adns_rrtype type,
adns_queryflags qf,
adns_rrtype *rrty, size_t *nrrty)
static void icb_addr(adns_query parent, adns_query child);
static void addr_subqueries(adns_query qu, struct timeval now,
static void icb_addr(adns_query parent, adns_query child);
static void addr_subqueries(adns_query qu, struct timeval now,
- const byte *qd_dgram, int qd_dglen,
- const adns_rrtype *rrty, size_t nrrty)
+ const byte *qd_dgram, int qd_dglen)
{
int i, err, id;
adns_query cqu;
{
int i, err, id;
adns_query cqu;
*/
memset(&ctx, 0, sizeof(ctx));
ctx.callback = icb_addr;
*/
memset(&ctx, 0, sizeof(ctx));
ctx.callback = icb_addr;
- for (i = 0; i < nrrty; i++) {
- err = adns__mkquery_frdgram(qu->ads, &qu->vb, &id, qd_dgram,
- qd_dglen, DNS_HDRSIZE, rrty[i], qf);
+ qu->t.addr.onrrty = qu->t.addr.nrrty;
+ for (i = 0; i < qu->t.addr.nrrty; i++) {
+ err = adns__mkquery_frdgram(qu->ads, &qu->vb, &id, qd_dgram, qd_dglen,
+ DNS_HDRSIZE, qu->t.addr.rrty[i], qf);
- err = adns__internal_submit(qu->ads, &cqu, qu->typei, rrty[i],
+ err = adns__internal_submit(qu->ads, &cqu, qu->typei, qu->t.addr.rrty[i],
&qu->vb, id, qf, now, &ctx);
if (err) goto x_error;
cqu->answer->rrsz = qu->answer->rrsz;
&qu->vb, id, qf, now, &ctx);
if (err) goto x_error;
cqu->answer->rrsz = qu->answer->rrsz;
*/
adns_state ads = parent->ads;
*/
adns_state ads = parent->ads;
adns_status err;
adns_rrtype type =
(adns_r_addr & adns_rrt_reprmask) |
(parent->answer->type & ~adns_rrt_reprmask);
adns_status err;
adns_rrtype type =
(adns_r_addr & adns_rrt_reprmask) |
(parent->answer->type & ~adns_rrt_reprmask);
- err = adns__internal_submit(ads, query_r, adns__findtype(adns_r_addr),
+ err = adns__internal_submit(ads, &qu, adns__findtype(adns_r_addr),
type, qumsg_vb, id, flags | adns__qf_nosend,
now, ctx);
if (err) return err;
type, qumsg_vb, id, flags | adns__qf_nosend,
now, ctx);
if (err) return err;
- (*query_r)->parent = parent;
- LIST_LINK_TAIL_PART(parent->children, *query_r, siblings.);
- addr_subqueries(*query_r, now, parent->query_dgram,
- parent->query_dglen, rrty, nrrty);
+ qu->parent = parent;
+ LIST_LINK_TAIL_PART(parent->children, qu, siblings.);
+
+ memcpy(qu->t.addr.rrty, rrty, nrrty*sizeof(*rrty));
+ qu->t.addr.nrrty = nrrty;
+ addr_subqueries(qu, now, parent->query_dgram, parent->query_dglen);
+ *query_r = qu;
+static void done_addr_type(adns_query qu, adns_rrtype type)
+{
+ size_t i;
+
+ for (i = 0; i < qu->t.addr.nrrty && type != qu->t.addr.rrty[i]; i++);
+ assert(i < qu->t.addr.nrrty);
+ qu->t.addr.rrty[i] = qu->t.addr.rrty[--qu->t.addr.nrrty];
+ qu->t.addr.rrty[qu->t.addr.nrrty] = type;
+}
+
static void icb_addr(adns_query parent, adns_query child)
{
adns_state ads = parent->ads;
static void icb_addr(adns_query parent, adns_query child)
{
adns_state ads = parent->ads;
struct timeval tvbuf;
adns_status err;
const struct timeval *now = 0;
struct timeval tvbuf;
adns_status err;
const struct timeval *now = 0;
- adns_rrtype rrty[ADDR_MAXRRTYPES], ty;
- byte *p;
- adns_rr_addr *a;
- int i, j, id;
- size_t nrrty;
if (!(child->flags & adns__qf_addr_cname) &&
(parent->flags & adns__qf_addr_answer) &&
if (!(child->flags & adns__qf_addr_cname) &&
(parent->flags & adns__qf_addr_answer) &&
adns__transfer_interim(child, parent, cans->rrs.bytes);
pans->rrs.bytes = cans->rrs.bytes;
pans->nrrs = cans->nrrs;
adns__transfer_interim(child, parent, cans->rrs.bytes);
pans->rrs.bytes = cans->rrs.bytes;
pans->nrrs = cans->nrrs;
+ parent->t.addr.nrrty = parent->t.addr.onrrty;
+ done_addr_type(parent, cans->type);
err = copy_cname_from_child(parent, child); if (err) goto x_err;
}
err = copy_cname_from_child(parent, child); if (err) goto x_err;
}
adns_r_addr, parent->flags);
if (err) goto x_err;
adns_r_addr, parent->flags);
if (err) goto x_err;
- /* Work out which address rrtypes we want but don't have. */
- addr_rrtypes(ads, pans->type, parent->flags, rrty, &nrrty);
- for (i = 0, p = pans->rrs.bytes; i < pans->nrrs; i++, p += pans->rrsz) {
- a = (adns_rr_addr *)p;
- ty = 0;
- switch (a->addr.sa.sa_family) {
- case AF_INET: ty = adns_r_a; break;
- case AF_INET6: ty = adns_r_aaaa; break;
- }
- assert(ty);
- for (j = 0; j < nrrty && ty != (rrty[j] & adns_rrt_typemask); j++);
- if (j < nrrty) rrty[j] = rrty[--nrrty];
- }
- assert(nrrty);
-
/* Now cancel the remaining children, and try again with the CNAME we've
* settled on.
*/
adns__cancel_children(parent);
adns__must_gettimeofday(ads, &now, &tvbuf);
/* Now cancel the remaining children, and try again with the CNAME we've
* settled on.
*/
adns__cancel_children(parent);
adns__must_gettimeofday(ads, &now, &tvbuf);
- if (now) {
- addr_subqueries(parent, *now, child->vb.buf,
- child->vb.used, rrty, nrrty);
- }
+ if (now) addr_subqueries(parent, *now, child->vb.buf, child->vb.used);
&pans->rrs.addr, &pans->nrrs,
cans->rrs.addr, cans->nrrs);
if (err) goto x_err;
&pans->rrs.addr, &pans->nrrs,
cans->rrs.addr, cans->nrrs);
if (err) goto x_err;
+ done_addr_type(parent, cans->type);
if (parent->children.head) LIST_LINK_TAIL(ads->childw, parent);
else if (!pans->nrrs) adns__query_fail(parent, adns_s_nodata);
if (parent->children.head) LIST_LINK_TAIL(ads->childw, parent);
else if (!pans->nrrs) adns__query_fail(parent, adns_s_nodata);
static void qs_addr(adns_query qu, struct timeval now)
{
static void qs_addr(adns_query qu, struct timeval now)
{
- adns_rrtype rrty[ADDR_MAXRRTYPES];
- size_t nrrty;
-
- addr_rrtypes(qu->ads, qu->answer->type, qu->flags, rrty, &nrrty);
- addr_subqueries(qu, now, qu->query_dgram,
- qu->query_dglen, rrty, nrrty);
+ addr_rrtypes(qu->ads, qu->answer->type, qu->flags,
+ qu->t.addr.rrty, &qu->t.addr.nrrty);
+ addr_subqueries(qu, now, qu->query_dgram, qu->query_dglen);