chiark / gitweb /
Fix CNAME hack.
authorMark Wooding <mdw@distorted.org.uk>
Tue, 13 May 2014 14:01:45 +0000 (15:01 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Tue, 13 May 2014 14:01:45 +0000 (15:01 +0100)
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.

src/internal.h
src/types.c

index 40da52d5bda5ffd05343b8e24a6780969d6cda3c..a9ea879e6757af39d489c678cccf8b1f5d99d356 100644 (file)
@@ -72,6 +72,8 @@ typedef unsigned char byte;
 #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
 
@@ -293,6 +295,13 @@ struct adns__query {
   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:
index f7a0e4dc62146d6205a574cffa0f45d9ed14f7e4..582ddb58bdab3da6ff77830ba5348da6c84a0047 100644 (file)
@@ -479,8 +479,6 @@ static adns_status cs_addr(vbuf *vb, const void *datap) {
   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)
@@ -524,8 +522,7 @@ static adns_status append_addrs(adns_query qu, adns_query from, size_t rrsz,
 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;
@@ -543,11 +540,12 @@ static void addr_subqueries(adns_query qu, struct timeval now,
    */
   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);
     if (err) goto x_error;
-    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;
@@ -579,20 +577,24 @@ static adns_status addr_submit(adns_query parent, adns_query *query_r,
    */
 
   adns_state ads = parent->ads;
+  adns_query qu;
   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;
 
-  (*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;
   return adns_s_ok;
 }
 
@@ -607,6 +609,16 @@ static adns_status copy_cname_from_child(adns_query parent, adns_query child)
   return adns_s_ok;
 }
 
+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;
@@ -614,11 +626,7 @@ static void icb_addr(adns_query parent, adns_query child)
   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;
+  int id;
 
   if (!(child->flags & adns__qf_addr_cname) &&
       (parent->flags & adns__qf_addr_answer) &&
@@ -638,6 +646,8 @@ 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;
+      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;
     }
 
@@ -651,30 +661,12 @@ static void icb_addr(adns_query parent, adns_query child)
                        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);
-    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);
     return;
   }
 
@@ -706,6 +698,7 @@ static void icb_addr(adns_query parent, adns_query child)
                     &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);
@@ -719,12 +712,9 @@ x_err:
 
 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);
 }
 
 /*