chiark / gitweb /
src/types.c, regress/: Use checklabel hook to parse PTR query domains.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 1 Jun 2014 20:50:59 +0000 (21:50 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Fri, 13 Jun 2014 08:57:41 +0000 (09:57 +0100)
A PTR with forward-lookup checking needs to parse the original question
into an address, so as to have something to compare the results of the
forward queries against.  Previously this was done in pa_ptr, when the
first PTR answer came in.  But parsing can fail, and is a simple
syntactic computation on the input domain name, so it seems rather
unfortunate to delay checking the name until an answer has come in.  Now
that we have the checklabel hook, then, we might as well use it here.
(Indeed, this is in fact the reason for introducing it.)

Unfortunately, this check now rejects a number of queries early, which
previously would have resulted in a query and maybe a NODATA or NXDOMAIN
answer, but in exactly the way we just rigged all of the test cases.  So
we remove the temporary hack to adns_submit and everything stays good.
Right?

Signed-off-by: Mark Wooding <mdw@distorted.org.uk>
src/internal.h
src/query.c
src/types.c

index 5f8892e40b07bd58d776ca7cbeb6d1a73034d111..c2876bfae2913b28e6f6658926fb84bfa96d33ab 100644 (file)
@@ -125,7 +125,7 @@ typedef struct {
 } parseinfo;
 
 union checklabel_state {
-  int dummy;
+  struct { byte ipv[4]; } ptr;
 };
 
 typedef struct {
index dd2a47a6b0851001771f05e599860cd8709424b6..a3ce68d8051aa7c821af959c0cbf9e19e53ad378 100644 (file)
@@ -294,17 +294,7 @@ int adns_submit(adns_state ads,
     ol--;
   }
 
-/* temporary hack */
-#define CHECK_PTR do {                                                 \
-  if (type == adns_r_ptr && (ol < 5 ||                                 \
-                            strncmp(owner + ol - 5, ".arpa", 5))) {    \
-    ads->nextid++; adns__autosys(ads,now);                             \
-    stat= adns_s_querydomainwrong; goto x_adnsfail;                    \
-  }                                                                    \
-} while (0)
-
   if (flags & adns_qf_search) {
-    CHECK_PTR;
     r= adns__vbuf_append(&qu->search_vb,owner,ol);
     if (!r) { stat= adns_s_nomemory; goto x_adnsfail; }
 
@@ -316,15 +306,12 @@ int adns_submit(adns_state ads,
     if (flags & adns_qf_owner) {
       if (!save_owner(qu,owner,ol)) { stat= adns_s_nomemory; goto x_adnsfail; }
     }
-    CHECK_PTR;
     query_simple(ads,qu, owner,ol, typei,flags, now);
   }
   adns__autosys(ads,now);
   adns__consistency(ads,qu,cc_entex);
   return 0;
 
-#undef CHECK_PTR
-
  x_adnsfail:
   adns__query_fail(qu,stat);
   adns__consistency(ads,qu,cc_entex);
index 675442c3344d6c878a94c5e7fa03aec0c8b113ff..d463b7f9664aa715f045fee67af76d2e829ec8df 100644 (file)
@@ -58,7 +58,7 @@
  * _mx                        (pa,di)
  * _inthostaddr               (mf,cs)
  * _inthost                  (cs)
- * _ptr                       (pa)
+ * _ptr                       (ckl,pa +icb_ptr)
  * _strpair                   (mf)
  * _intstrpair                (mf)
  * _hinfo                     (pa)
@@ -704,9 +704,43 @@ static adns_status cs_inthost(vbuf *vb, const void *datap) {
 }
 
 /*
- * _ptr   (pa, +icb_ptr)
+ * _ptr   (ckl,pa +icb_ptr)
  */
 
+static adns_status ckl_ptr(adns_state ads, adns_queryflags flags,
+                          union checklabel_state *cls, qcontext *ctx,
+                          int labnum, const char *label, int lablen) {
+  static const char *const (expectdomain[])= { DNS_INADDR_ARPA };
+  adns_rr_addr *ap;
+  char *ep;
+  const char *ed;
+  char labbuf[4];
+  int l;
+
+  if (labnum < 4) {
+    if (lablen<=0 || lablen>3) return adns_s_querydomainwrong;
+    memcpy(labbuf, label, lablen);
+    labbuf[lablen]= 0;
+    cls->ptr.ipv[3-labnum]= strtoul(labbuf,&ep,10);
+    if (*ep) return adns_s_querydomainwrong;
+    if (lablen>1 && *label=='0') return adns_s_querydomainwrong;
+  } else if (labnum < 4 + sizeof(expectdomain)/sizeof(*expectdomain)) {
+    ed= expectdomain[labnum-4];
+    l= strlen(ed);
+    if (lablen != l || memcmp(label, ed, l)) return adns_s_querydomainwrong;
+  } else {
+    if (lablen) return adns_s_querydomainwrong;
+    ap= &ctx->tinfo.ptr_addr;
+    ap->len= sizeof(struct sockaddr_in);
+    memset(&ap->addr,0,sizeof(ap->addr.inet));
+    ap->addr.inet.sin_family= AF_INET;
+    ap->addr.inet.sin_addr.s_addr=
+      htonl((cls->ptr.ipv[0]<<24) | (cls->ptr.ipv[1]<<16) |
+           (cls->ptr.ipv[2]<< 8) | (cls->ptr.ipv[3]));
+  }
+  return adns_s_ok;
+}
+
 static void icb_ptr(adns_query parent, adns_query child) {
   adns_answer *cans= child->answer;
   const adns_rr_addr *queried, *found;
@@ -740,16 +774,9 @@ static void icb_ptr(adns_query parent, adns_query child) {
 
 static adns_status pa_ptr(const parseinfo *pai, int dmstart,
                          int max, void *datap) {
-  static const char *const (expectdomain[])= { DNS_INADDR_ARPA };
-  
   char **rrp= datap;
   adns_status st;
-  adns_rr_addr *ap;
-  findlabel_state fls;
-  char *ep;
-  byte ipv[4];
-  char labbuf[4];
-  int cbyte, i, lablen, labstart, l, id;
+  int cbyte, id;
   adns_query nqu;
   qcontext ctx;
 
@@ -759,38 +786,6 @@ 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.tinfo.ptr_addr;
-  if (!ap->len) {
-    adns__findlabel_start(&fls, pai->ads, -1, pai->qu,
-                         pai->qu->query_dgram, pai->qu->query_dglen,
-                         pai->qu->query_dglen, DNS_HDRSIZE, 0);
-    for (i=0; i<4; i++) {
-      st= adns__findlabel_next(&fls,&lablen,&labstart); assert(!st);
-      if (lablen<=0 || lablen>3) return adns_s_querydomainwrong;
-      memcpy(labbuf, pai->qu->query_dgram + labstart, lablen);
-      labbuf[lablen]= 0;
-      ipv[3-i]= strtoul(labbuf,&ep,10);
-      if (*ep) return adns_s_querydomainwrong;
-      if (lablen>1 && pai->qu->query_dgram[labstart]=='0')
-       return adns_s_querydomainwrong;
-    }
-    for (i=0; i<sizeof(expectdomain)/sizeof(*expectdomain); i++) {
-      st= adns__findlabel_next(&fls,&lablen,&labstart); assert(!st);
-      l= strlen(expectdomain[i]);
-      if (lablen != l ||
-         memcmp(pai->qu->query_dgram + labstart, expectdomain[i], l))
-       return adns_s_querydomainwrong;
-    }
-    st= adns__findlabel_next(&fls,&lablen,0); assert(!st);
-    if (lablen) return adns_s_querydomainwrong;
-    
-    ap->len= sizeof(struct sockaddr_in);
-    memset(&ap->addr,0,sizeof(ap->addr.inet));
-    ap->addr.inet.sin_family= AF_INET;
-    ap->addr.inet.sin_addr.s_addr=
-      htonl((ipv[0]<<24) | (ipv[1]<<16) | (ipv[2]<<8) | (ipv[3]));
-  }
-
   st= adns__mkquery_frdgram(pai->ads, &pai->qu->vb, &id,
                            pai->dgram, pai->dglen, dmstart,
                            adns_r_addr, adns_qf_quoteok_query);
@@ -1260,7 +1255,8 @@ DEEP_TYPE(srv_raw,"SRV",  "raw",srvraw ,   srvraw,  srv,   srvraw,
 
 FLAT_TYPE(addr,   "A",  "addr", addr,      addr,    addr,  addr            ),
 DEEP_TYPE(ns,     "NS", "+addr",hostaddr,  hostaddr,hostaddr,hostaddr      ),
-DEEP_TYPE(ptr,    "PTR","checked",str,     ptr,     0,     domain          ),
+DEEP_TYPE(ptr,    "PTR","checked",str,     ptr,     0,     domain,
+                                                      .checklabel= ckl_ptr),
 DEEP_TYPE(mx,     "MX", "+addr",inthostaddr,mx,     mx,    inthostaddr,    ),
 DEEP_TYPE(srv,    "SRV","+addr",srvha,     srvha,   srv,   srvha,
                              .checklabel= ckl_srv, .postsort= postsort_srv),