chiark / gitweb /
src/types.c: Use the new `checklabel' machinery for PTR queries.
authorMark Wooding <mdw@distorted.org.uk>
Wed, 21 May 2014 08:40:33 +0000 (09:40 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Wed, 21 May 2014 08:40:33 +0000 (09:40 +0100)
Previously we'd check the query name and parse it into an address while
parsing the answer to the initial query, which means that you only get
an error about the name being malformed after waiting for the answer.
Now we have a better placed hook for dealing with this, so we should use
it.

src/internal.h
src/types.c

index b602c92aeb2858f5d3be5867a50db4c31cea6032..3e85a5872e050b0a9594cb9c2ae0519bfd148d03 100644 (file)
@@ -130,7 +130,11 @@ union gen_addr {
 };
 
 union checklabel_state {
-  int dummy;
+  struct {
+#define PTR_NDOMAIN 2
+    unsigned domainmap;                        /* which domains are still live */
+    byte ipv[PTR_NDOMAIN][32];         /* address components so far */
+  } ptr;
 };
 
 typedef struct {
@@ -159,11 +163,13 @@ typedef struct {
   void (*callback)(adns_query parent, adns_query child);
 
   union {
-    struct afinfo_addr ptr_parent_addr;
     adns_rr_hostaddr *hostaddr;
   } pinfo; /* state for use by parent's callback function */
 
   union {
+    struct {
+      struct afinfo_addr addr;
+    } ptr;
     struct {
       unsigned want, have;
     } addr;
index 4264754e5e517039d95541c56d9d79c103807208..ff3691b5c103250eb5ec5c5ea835d6ceedc36024 100644 (file)
@@ -1149,7 +1149,7 @@ static void icb_ptr(adns_query parent, adns_query child) {
     return;
   }
 
-  queried= &parent->ctx.pinfo.ptr_parent_addr.addr;
+  queried= &parent->ctx.tinfo.ptr.addr.addr;
   for (i=0, found=cans->rrs.bytes; i<cans->nrrs; i++, found += cans->rrsz) {
     if (!memcmp(queried,found,cans->rrsz)) {
       if (!parent->children.head) {
@@ -1165,24 +1165,75 @@ static void icb_ptr(adns_query parent, adns_query child) {
   adns__query_fail(parent,adns_s_inconsistent);
 }
 
+static const struct ptr_expectdomain {
+  const afinfo *ai;
+  const char *const tail[3];
+} ptr_expectdomain[PTR_NDOMAIN] = {
+  { &adns__inet_afinfo, { DNS_INADDR_ARPA, 0 } },
+  { &adns__inet6_afinfo, { DNS_IP6_ARPA, 0 } }
+};
+
+static adns_status ckl_ptr(adns_state ads, adns_queryflags flags,
+                          union checklabel_state *css, qcontext *ctx,
+                          int labnum, const char *label, int lablen)
+{
+  int i, found, ac;
+  unsigned f = labnum ? css->ptr.domainmap : (1 << PTR_NDOMAIN) - 1;
+  unsigned d;
+  const char *tp;
+  const struct ptr_expectdomain *ed;
+  struct afinfo_addr *ap;
+
+  if (lablen) {
+    for (ed = ptr_expectdomain, i = 0, d = 1;
+        i < PTR_NDOMAIN;
+        ed++, i++, d <<= 1) {
+      if (!(f & d)) continue;
+      if (labnum < ed->ai->nrevcomp) {
+       ac = ed->ai->rev_parsecomp(label, lablen);
+       if (ac < 0) goto mismatch;
+       assert(labnum < sizeof(css->ptr.ipv[i]));
+       css->ptr.ipv[i][labnum] = ac;
+      } else {
+       tp = ed->tail[labnum - ed->ai->nrevcomp];
+       if (!tp || strncmp(label, tp, lablen) != 0 || tp[lablen])
+         goto mismatch;
+      }
+      continue;
+
+    mismatch:
+      f &= ~d;
+      if (!f) return adns_s_querydomainwrong;
+    }
+  } else {
+    found = -1;
+    for (ed = ptr_expectdomain, i = 0, d = 1;
+        i < PTR_NDOMAIN;
+        ed++, i++, d <<= 1) {
+      if (!(f & d)) continue;
+      if (labnum >= ed->ai->nrevcomp && !ed->tail[labnum - ed->ai->nrevcomp])
+       { found = i; continue; }
+      f &= ~d;
+      if (!f) return adns_s_querydomainwrong;
+    }
+    assert(found >= 0 && f == (1 << found));
+
+    ed = &ptr_expectdomain[found];
+    ap = &ctx->tinfo.ptr.addr;
+    ap->ai = ed->ai;
+    ed->ai->rev_mkaddr(&ap->addr, css->ptr.ipv[found]);
+  }
+
+  css->ptr.domainmap = f;
+  return adns_s_ok;
+}
+
 static adns_status pa_ptr(const parseinfo *pai, int dmstart,
                          int max, void *datap) {
-  static const struct {
-    const afinfo *ai;
-    const char *const tail[3];
-  } expectdomain[] = {
-    { &adns__inet_afinfo, { DNS_INADDR_ARPA, 0 } },
-    { &adns__inet6_afinfo, { DNS_IP6_ARPA, 0 } }
-  };
-  enum { n_ed = sizeof(expectdomain)/sizeof(expectdomain[0]) };
-  
   char **rrp= datap;
   adns_status st;
   struct afinfo_addr *ap;
-  findlabel_state fls;
-  byte ipv[n_ed][32];
-  int cbyte, i, j, foundj = -1, lablen, labstart, id, f, ac;
-  const char *tp;
+  int cbyte, id;
   adns_query nqu;
   qcontext ctx;
 
@@ -1192,53 +1243,8 @@ static adns_status pa_ptr(const parseinfo *pai, int dmstart,
   if (st) return st;
   if (cbyte != max) return adns_s_invaliddata;
 
-  ap= &pai->qu->ctx.pinfo.ptr_parent_addr;
-  if (!ap->ai) {
-    adns__findlabel_start(&fls, pai->ads, -1, pai->qu,
-                         pai->qu->query_dgram, pai->qu->query_dglen,
-                         pai->qu->query_dglen, DNS_HDRSIZE, 0);
-
-    f = (1 << n_ed) - 1; /* superposition of address types */
-    for (i = 0;; i++) {
-      st= adns__findlabel_next(&fls,&lablen,&labstart); assert(!st);
-      if (lablen <= 0) break;
-      for (j = 0; j < n_ed; j++) {
-       if (!(f & (1 << j))) continue;
-       if (i < expectdomain[j].ai->nrevcomp) {
-         ac = expectdomain[j].ai->rev_parsecomp(
-           pai->qu->query_dgram + labstart, lablen);
-         if (ac < 0) goto mismatch;
-         assert(i < sizeof(ipv[j]));
-         ipv[j][i] = ac;
-       } else {
-         tp = expectdomain[j].tail[i - expectdomain[j].ai->nrevcomp];
-         if (!tp ||
-             strncmp(pai->qu->query_dgram + labstart, tp, lablen) != 0 ||
-             tp[lablen] != 0)
-           goto mismatch;
-       }
-       continue;
-
-      mismatch:
-       f &= ~(1 << j);
-       if (!f) return adns_s_querydomainwrong;
-      }
-    }
-
-    if (lablen < 0) return adns_s_querydomainwrong;
-    for (j = 0; j < n_ed; j++) {
-      if (!(f & (1 << j))) continue;
-      if (i >= expectdomain[j].ai->nrevcomp &&
-         !expectdomain[j].tail[i - expectdomain[j].ai->nrevcomp])
-       { foundj = j; continue; }
-      f &= ~(1 << j);
-      if (!f) return adns_s_querydomainwrong;
-    }
-    assert(foundj >= 0 && f == (1 << foundj)); /* collapsed to a single type */
-
-    ap->ai = expectdomain[foundj].ai;
-    ap->ai->rev_mkaddr(&ap->addr, ipv[foundj]);
-  }
+  ap= &pai->qu->ctx.tinfo.ptr.addr;
+  assert(ap->ai);
 
   st= adns__mkquery_frdgram(pai->ads, &pai->qu->vb, &id,
                            pai->dgram, pai->dglen, dmstart,
@@ -1715,7 +1721,8 @@ XTRA_TYPE(srv_raw,"SRV",  "raw",srvraw , pa_srvraw,  di_srv,   cs_srvraw,
 XTRA_TYPE(addr,   "A",  "addr", addr,    pa_addr,    di_addr,  cs_addr,
                            mf_flat, adns__ckl_hostname, 0, gsz_addr, qs_addr),
 DEEP_TYPE(ns,     "NS", "+addr",hostaddr,pa_hostaddr,di_hostaddr,cs_hostaddr ),
-DEEP_TYPE(ptr,    "PTR","checked",str,   pa_ptr,     0,        cs_domain     ),
+XTRA_TYPE(ptr,    "PTR","checked",str,   pa_ptr,     0,        cs_domain,
+                                                    mf_str, ckl_ptr, 0, 0, 0),
 DEEP_TYPE(mx,     "MX", "+addr",inthostaddr,pa_mx,   di_mx,    cs_inthostaddr),
 XTRA_TYPE(srv,    "SRV","+addr",srvha,   pa_srvha,   di_srv,   cs_srvha,
                                        mf_srvha, ckl_srv, postsort_srv, 0, 0),