Now we have a vector of query types we might want to make, and a pair of
bitmaps tracking whether (a) we want to issue that kind of query,
and (b) whether we've had an answer to it yet. This replaces
the (sometimes tricky) messing about with raw rrtype vectors.
As a bonus, these bitmaps are now set in the context structure, where
they can be pushed through adns__internal_submit and into qs_addr, so we
no longer need adns__qf_nosend. This is, accordingly, killed.
#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 MAX_ADDRSTRLEN 64
#define STRINGIFY(x) REALLY_STRINGIFY(x)
#define MAX_ADDRSTRLEN 64
#define STRINGIFY(x) REALLY_STRINGIFY(x)
- adns__qf_senddirect = 0x00100000,/* don't call the `query_send' type hook */
- adns__qf_nosend = 0x00200000,/* don't send the query when submitting */
adns__qf_addr_answer= 0x01000000,/* addr query received an answer */
adns__qf_addr_cname = 0x02000000 /* addr subquery performed on cname */
};
adns__qf_addr_answer= 0x01000000,/* addr query received an answer */
adns__qf_addr_cname = 0x02000000 /* addr subquery performed on cname */
};
- size_t nrrty, onrrty;
- adns_rrtype rrty[ADDR_MAXRRTYPES];
} addr;
} tinfo; /* type-specific state for the query itself: zero-init if you
* don't know better. */
} addr;
} tinfo; /* type-specific state for the query itself: zero-init if you
* don't know better. */
qu->query_dglen= qu->vb.used;
memcpy(qu->query_dgram,qu->vb.buf,qu->vb.used);
qu->query_dglen= qu->vb.used;
memcpy(qu->query_dgram,qu->vb.buf,qu->vb.used);
- if (flags & adns__qf_nosend)
- ;
- else if (typei->query_send && !(flags & adns__qf_senddirect))
- typei->query_send(qu,now);
- else
- adns__query_send(qu, now);
+ if (typei->query_send) typei->query_send(qu,now);
+ else adns__query_send(qu, now);
}
adns_status adns__internal_submit(adns_state ads, adns_query *query_r,
}
adns_status adns__internal_submit(adns_state ads, adns_query *query_r,
const qcontext *ctx) {
adns_query qu;
const qcontext *ctx) {
adns_query qu;
- qu= query_alloc(ads,typei,type,flags & ~adns__qf_nosend,now);
+ qu= query_alloc(ads,typei,type,flags,now);
if (!qu) { adns__vbuf_free(qumsg_vb); return adns_s_nomemory; }
*query_r= qu;
if (!qu) { adns__vbuf_free(qumsg_vb); return adns_s_nomemory; }
*query_r= qu;
static const typeinfo tinfo_addrsub;
static const typeinfo tinfo_addrsub;
+#define ADDR_RRTYPES(_) _(a) _(aaaa)
+
+static const adns_rrtype addr_all_rrtypes[] = {
+#define RRTY_CODE(ty) adns_r_##ty,
+ ADDR_RRTYPES(RRTY_CODE)
+#undef RRTY_CODE
+};
+
+enum {
+#define RRTY_INDEX(ty) addr__ri_##ty,
+ ADDR_RRTYPES(RRTY_INDEX)
+#undef RRTY_INDEX
+ addr_nrrtypes,
+#define RRTY_FLAG(ty) addr_rf_##ty = 1 << addr__ri_##ty,
+ ADDR_RRTYPES(RRTY_FLAG)
+ addr__rrty_hunoz
+#undef RRTY_FLAG
+};
+
+static unsigned addr_rrtypeflag(adns_rrtype type)
+{
+ int i;
+
+ type &= adns_rrt_typemask;
+ for (i = 0; i < addr_nrrtypes && type != addr_all_rrtypes[i]; i++);
+ assert(i < addr_nrrtypes);
+ return 1 << i;
+}
+
/* About CNAME handling in addr queries.
*
* A user-level addr query is translated into a number of protocol-level
/* About CNAME handling in addr queries.
*
* A user-level addr query is translated into a number of protocol-level
return csp_addr(vb,rrp);
}
return csp_addr(vb,rrp);
}
-static void addr_rrtypes(adns_state ads, adns_rrtype type,
- adns_queryflags qf,
- adns_rrtype *rrty, size_t *nrrty)
+static unsigned addr_rrtypes(adns_state ads, adns_rrtype type,
+ adns_queryflags qf)
- size_t n = 0;
- adns_rrtype qtf = type & adns__qtf_deref;
adns_queryflags permitaf = 0, hackaf = 0;
adns_queryflags permitaf = 0, hackaf = 0;
if (!(qf & (adns_qf_ipv4_only | adns_qf_ipv6_only)))
qf |= adns_qf_ipv4_only | adns_qf_ipv6_only;
if (!(qf & (adns_qf_ipv4_only | adns_qf_ipv6_only)))
qf |= adns_qf_ipv4_only | adns_qf_ipv6_only;
qf &= hackaf | permitaf | ~adns__qf_afmask;
}
qf &= hackaf | permitaf | ~adns__qf_afmask;
}
- if (qf & adns_qf_ipv4_only) rrty[n++] = adns_r_a | qtf;
- if (qf & adns_qf_ipv6_only) rrty[n++] = adns_r_aaaa | qtf;
+ if (qf & adns_qf_ipv4_only) want |= addr_rf_a;
+ if (qf & adns_qf_ipv6_only) want |= addr_rf_aaaa;
}
static int gsz_addr(adns_rrtype type)
}
static int gsz_addr(adns_rrtype type)
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,
+ adns_queryflags qf_extra,
const byte *qd_dgram, int qd_dglen)
{
int i, err, id;
adns_query cqu;
const byte *qd_dgram, int qd_dglen)
{
int i, err, id;
adns_query cqu;
- adns_queryflags qf =qu->flags & ~adns_qf_search;
+ adns_queryflags qf = (qu->flags & ~adns_qf_search) | qf_extra;
+ adns_rrtype qtf = qu->answer->type & adns__qtf_deref;
+ unsigned which = qu->ctx.tinfo.addr.want & ~qu->ctx.tinfo.addr.have;
- /* This always makes child queries, even if there's only the one. This
- * seems wasteful, but there's only one case where it'd be safe -- namely
- * IPv4-only -- and that's not the case I want to optimize.
- */
memset(&ctx, 0, sizeof(ctx));
ctx.callback = icb_addr;
memset(&ctx, 0, sizeof(ctx));
ctx.callback = icb_addr;
- qu->ctx.tinfo.addr.onrrty = qu->ctx.tinfo.addr.nrrty;
- for (i = 0; i < qu->ctx.tinfo.addr.nrrty; i++) {
+ for (i = 0; i < addr_nrrtypes; i++) {
+ if (!(which & (1 << i))) continue;
err = adns__mkquery_frdgram(qu->ads, &qu->vb, &id, qd_dgram, qd_dglen,
err = adns__mkquery_frdgram(qu->ads, &qu->vb, &id, qd_dgram, qd_dglen,
- DNS_HDRSIZE, qu->ctx.tinfo.addr.rrty[i], qf);
+ DNS_HDRSIZE, addr_all_rrtypes[i], qf);
if (err) goto x_error;
err = adns__internal_submit(qu->ads, &cqu, &tinfo_addrsub,
if (err) goto x_error;
err = adns__internal_submit(qu->ads, &cqu, &tinfo_addrsub,
- qu->ctx.tinfo.addr.rrty[i],
+ addr_all_rrtypes[i] | qtf,
&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;
}
static adns_status addr_submit(adns_query parent, adns_query *query_r,
}
static adns_status addr_submit(adns_query parent, adns_query *query_r,
- vbuf *qumsg_vb, int id,
- const adns_rrtype *rrty, size_t nrrty,
+ vbuf *qumsg_vb, int id, unsigned want,
adns_queryflags flags, struct timeval now,
adns_queryflags flags, struct timeval now,
{
/* This is effectively a substitute for adns__internal_submit, intended for
* the case where the caller (possibly) only wants a subset of the
{
/* This is effectively a substitute for adns__internal_submit, intended for
* the case where the caller (possibly) only wants a subset of the
*
* 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
*
* 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).
+ * 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.
*/
adns_state ads = parent->ads;
*/
adns_state ads = parent->ads;
(adns_r_addr & adns_rrt_reprmask) |
(parent->answer->type & ~adns_rrt_reprmask);
(adns_r_addr & adns_rrt_reprmask) |
(parent->answer->type & ~adns_rrt_reprmask);
+ ctx->tinfo.addr.want = want;
+ ctx->tinfo.addr.have = 0;
err = adns__internal_submit(ads, &qu, 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);
+ type, qumsg_vb, id, flags, now, ctx);
if (err) return err;
qu->parent = parent;
LIST_LINK_TAIL_PART(parent->children, qu, siblings.);
if (err) return err;
qu->parent = parent;
LIST_LINK_TAIL_PART(parent->children, qu, siblings.);
-
- memcpy(qu->ctx.tinfo.addr.rrty, rrty, nrrty*sizeof(*rrty));
- qu->ctx.tinfo.addr.nrrty = nrrty;
- addr_subqueries(qu, now, qu->query_dgram, qu->query_dglen);
*query_r = qu;
return adns_s_ok;
}
*query_r = qu;
return adns_s_ok;
}
}
static void done_addr_type(adns_query qu, adns_rrtype type)
}
static void done_addr_type(adns_query qu, adns_rrtype type)
-{
- size_t i;
-
- for (i = 0;
- i < qu->ctx.tinfo.addr.nrrty &&
- type != qu->ctx.tinfo.addr.rrty[i];
- i++);
- assert(i < qu->ctx.tinfo.addr.nrrty);
- qu->ctx.tinfo.addr.rrty[i] =
- qu->ctx.tinfo.addr.rrty[--qu->ctx.tinfo.addr.nrrty];
- qu->ctx.tinfo.addr.rrty[qu->ctx.tinfo.addr.nrrty] = type;
-}
+ { qu->ctx.tinfo.addr.have |= addr_rrtypeflag(type); }
static void icb_addr(adns_query parent, adns_query child)
{
static void icb_addr(adns_query parent, adns_query child)
{
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->ctx.tinfo.addr.nrrty = parent->ctx.tinfo.addr.onrrty;
+ parent->ctx.tinfo.addr.have = 0;
done_addr_type(parent, cans->type);
err = copy_cname_from_child(parent, child); if (err) goto x_err;
}
done_addr_type(parent, cans->type);
err = copy_cname_from_child(parent, child); if (err) goto x_err;
}
* families. The child's vbuf looks handy for this.
*/
err = adns__mkquery(ads, &child->vb, &id, pans->cname,
* families. The child's vbuf looks handy for this.
*/
err = adns__mkquery(ads, &child->vb, &id, pans->cname,
- strlen(pans->cname), adns__findtype(adns_r_addr),
+ strlen(pans->cname), &tinfo_addrsub,
adns_r_addr, parent->flags);
if (err) goto x_err;
adns_r_addr, parent->flags);
if (err) goto x_err;
*/
adns__cancel_children(parent);
if (gettimeofday(&now, 0)) goto x_gtod;
*/
adns__cancel_children(parent);
if (gettimeofday(&now, 0)) goto x_gtod;
- addr_subqueries(parent, now, child->vb.buf, child->vb.used);
+ addr_subqueries(parent, now, adns__qf_addr_cname,
+ child->vb.buf, child->vb.used);
static void qs_addr(adns_query qu, struct timeval now)
{
static void qs_addr(adns_query qu, struct timeval now)
{
- addr_rrtypes(qu->ads, qu->answer->type, qu->flags,
- qu->ctx.tinfo.addr.rrty, &qu->ctx.tinfo.addr.nrrty);
- addr_subqueries(qu, now, qu->query_dgram, qu->query_dglen);
+ if (!qu->ctx.tinfo.addr.want) {
+ qu->ctx.tinfo.addr.want =
+ addr_rrtypes(qu->ads, qu->answer->type, qu->flags);
+ qu->ctx.tinfo.addr.have = 0;
+ }
+ addr_subqueries(qu, now, 0, qu->query_dgram, qu->query_dglen);
*/
static adns_status pap_findaddrs(const parseinfo *pai, adns_rr_hostaddr *ha,
*/
static adns_status pap_findaddrs(const parseinfo *pai, adns_rr_hostaddr *ha,
- adns_rrtype *rrty, size_t *nrrty_io,
- size_t addrsz, int *cbyte_io, int count,
- int dmstart) {
- int rri, naddrs, j;
+ unsigned *want_io, size_t addrsz,
+ int *cbyte_io, int count, int dmstart) {
+ int rri, naddrs;
+ unsigned typef, want = *want_io;
int type, class, rdlen, rdend, rdstart, ownermatched;
int type, class, rdlen, rdend, rdstart, ownermatched;
- size_t nrrty = *nrrty_io;
unsigned long ttl;
adns_status st;
unsigned long ttl;
adns_status st;
pai->dgram, pai->dglen, dmstart, &ownermatched);
if (st) return st;
if (!ownermatched || class != DNS_CLASS_IN) continue;
pai->dgram, pai->dglen, dmstart, &ownermatched);
if (st) return st;
if (!ownermatched || class != DNS_CLASS_IN) continue;
- for (j = 0; j < nrrty && type != (rrty[j] & adns_rrt_typemask); j++);
- if (j >= nrrty) continue;
- if (j < *nrrty_io) {
- (*nrrty_io)--;
- adns_rrtype t = rrty[j];
- rrty[j] = rrty[*nrrty_io];
- rrty[*nrrty_io] = t;
- }
+ typef = addr_rrtypeflag(type);
+ if (!(want & typef)) continue;
+ want &= ~typef;
if (!adns__vbuf_ensure(&pai->qu->vb, (naddrs+1)*addrsz)) R_NOMEM;
adns__update_expires(pai->qu,ttl,pai->now);
rdend = rdstart + rdlen;
if (!adns__vbuf_ensure(&pai->qu->vb, (naddrs+1)*addrsz)) R_NOMEM;
adns__update_expires(pai->qu,ttl,pai->now);
rdend = rdstart + rdlen;
if (st) return st;
ha->astatus= adns_s_ok;
if (st) return st;
ha->astatus= adns_s_ok;
adns__isort(ha->addrs, naddrs, addrsz, pai->qu->vb.buf,
div_addr, pai->ads);
}
}
adns__isort(ha->addrs, naddrs, addrsz, pai->qu->vb.buf,
div_addr, pai->ads);
}
}
int id;
adns_query nqu;
adns_queryflags nflags;
int id;
adns_query nqu;
adns_queryflags nflags;
- adns_rrtype rrty[ADDR_MAXRRTYPES];
- size_t nrrty;
size_t addrsz = gsz_addr(pai->qu->answer->type);
dmstart= cbyte= *cbyte_io;
size_t addrsz = gsz_addr(pai->qu->answer->type);
dmstart= cbyte= *cbyte_io;
- addr_rrtypes(pai->ads, pai->qu->answer->type,
- pai->qu->flags, rrty, &nrrty);
+ want = addr_rrtypes(pai->ads, pai->qu->answer->type, pai->qu->flags);
- st= pap_findaddrs(pai, rrp, rrty, &nrrty, addrsz,
- &cbyte, pai->nscount, dmstart);
+ st= pap_findaddrs(pai, rrp, &want, addrsz, &cbyte, pai->nscount, dmstart);
- if (!nrrty) return adns_s_ok;
+ if (!want) return adns_s_ok;
- st= pap_findaddrs(pai, rrp, rrty, &nrrty, addrsz,
- &cbyte, pai->arcount, dmstart);
+ st= pap_findaddrs(pai, rrp, &want, addrsz, &cbyte, pai->arcount, dmstart);
- if (!nrrty) return adns_s_ok;
+ if (!want) return adns_s_ok;
st= adns__mkquery_frdgram(pai->ads, &pai->qu->vb, &id,
pai->dgram, pai->dglen, dmstart,
st= adns__mkquery_frdgram(pai->ads, &pai->qu->vb, &id,
pai->dgram, pai->dglen, dmstart,
nflags= adns_qf_quoteok_query | (pai->qu->flags & adns__qf_afmask);
if (!(pai->qu->flags & adns_qf_cname_loose)) nflags |= adns_qf_cname_forbid;
nflags= adns_qf_quoteok_query | (pai->qu->flags & adns__qf_afmask);
if (!(pai->qu->flags & adns_qf_cname_loose)) nflags |= adns_qf_cname_forbid;
- st= addr_submit(pai->qu, &nqu, &pai->qu->vb, id, rrty, nrrty,
+ st= addr_submit(pai->qu, &nqu, &pai->qu->vb, id, want,
nflags, pai->now, &ctx);
if (st) return st;
nflags, pai->now, &ctx);
if (st) return st;