chiark / gitweb /
Import changes from chiark: cvs rdiff -u -r tochiark-1998-11-08 -r
authorian <ian>
Tue, 10 Nov 1998 01:03:54 +0000 (01:03 +0000)
committerian <ian>
Tue, 10 Nov 1998 01:03:54 +0000 (01:03 +0000)
fromchiark-1998-11-09 >~/private/t dnslib

client/adnstest.c
src/adns.h
src/general.c
src/internal.h
src/parse.c
src/reply.c
src/types.c

index 1752072..46a0258 100644 (file)
 
 #include <stdio.h>
 #include <unistd.h>
+#include <assert.h>
+#include <stdlib.h>
 
 #include "adns.h"
 
-int main(void) {
+static void failure(const char *what, adns_status st) {
+  fprintf(stderr,"adns failure: %s: %s\n",what,adns_strerror(st));
+  exit(2);
+}
+
+static const char *defaultargv[]= { "ns.chiark.greenend.org.uk", 0 };
+
+int main(int argc, const char *const *argv) {
   adns_state ads;
-  adns_query qu;
+  adns_query *qus, qu;
   adns_answer *ans;
-  int r;
+  const char *rrtn, *fmtn;
+  char *show;
+  int len, i, qc, qi;
+  adns_status r, ri;
+
+  if (argv[0] && argv[1]) argv++;
+  else argv= defaultargv;
+
+  for (qc=0; qc[argv]; qc++);
+  qus= malloc(sizeof(qus)*qc);
+  if (!qus) { perror("malloc qus"); exit(3); }
 
   r= adns_init(&ads,adns_if_debug|adns_if_noautosys,0);
-  if (r) { perror("init"); exit(2); }
+  if (r) failure("init",r);
+
+  for (qi=0; qi<qc; qi++) {
+    r= adns_submit(ads,argv[qi],adns_r_a,0,0,&qus[qi]);
+    if (r) failure("submit",r);
+  }
 
-  r= adns_submit(ads,"anarres.relativity.greenend.org.uk",adns_r_a,0,0,&qu);
-  if (r) { perror("submit"); exit(2); }
+  for (qi=0; qi<qc; qi++) {
+    qu= qus[qi];
+    r= adns_wait(ads,&qu,&ans,0);
+    if (r) failure("wait",r);
 
-  r= adns_wait(ads,&qu,&ans,0);
-  if (r) { perror("wait"); exit(2); }
+    ri= adns_rr_info(ans->type, &rrtn,&fmtn,&len, 0,0);
+    fprintf(stdout, "%s: %s; nrrs=%d; cname=%s; ",
+           argv[qi], adns_strerror(ans->status),
+           ans->nrrs, ans->cname ? ans->cname : "$");
+    fprintf(stdout, "type %s(%s) %s\n",
+           ri ? "?" : rrtn, ri ? "?" : fmtn ? fmtn : "-",
+           adns_strerror(ri));
+    if (ans->nrrs) {
+      assert(!ri);
+      for (i=0; i<ans->nrrs; i++) {
+       r= adns_rr_info(ans->type, 0,0,0, ans->rrs.bytes+i*len,&show);
+       if (r) failure("info",r);
+       printf(" %s\n",show);
+       free(show);
+      }
+    }
+    free(ans);
+  }
 
-  fprintf(stderr,"answer status %d type %d rrs %d cname %s\n",
-         ans->status,ans->type,ans->nrrs,
-         ans->cname ? ans->cname : "-");
-  
+  free(qus);
   exit(0);
 }
index 9f9cb12..a800813 100644 (file)
@@ -163,7 +163,7 @@ typedef struct {
 typedef struct {
   adns_status status;
   char *cname; /* always NULL if query was for CNAME records */
-  adns_rrtype type;
+  adns_rrtype type; /* guaranteed to be same as in query */
   int nrrs, rrsz;
   union {
     void *untyped;
@@ -288,6 +288,34 @@ void adns_interest(adns_state, int *maxfd_io, fd_set *readfds_io,
  *  }
  */
 
+adns_status adns_rr_info(adns_rrtype type,
+                        const char **rrtname_r, const char **fmtname_r,
+                        int *len_r,
+                        const void *datap, char **data_r);
+/* Gets information in human-readable (but non-i18n) form
+ * for eg debugging purposes.  type must be specified,
+ * and the official name of the corresponding RR type will
+ * be returned in *rrtname_r, and information about the processing
+ * style in *fmtname_r.  The length of the table entry in an answer
+ * for that type will be returned in in *len_r.
+ * Any or all of rrtname_r, fmtname_r and len_r may be 0.
+ * If fmtname_r is non-null then *fmtname_r may be
+ * null on return, indicating that no special processing is
+ * involved.
+ *
+ * data_r be must be non-null iff datap is.  In this case
+ * *data_r will be set to point to a human-readable text
+ * string representing the RR data.  The text will have
+ * been obtained from malloc() and must be freed by the caller.
+ *
+ * Usually this routine will succeed.  Possible errors include:
+ *  adns_s_nomemory
+ *  adns_s_notimplemented (RR type not known)
+ *  adns_s_invaliddata (*datap contained garbage)
+ * If an error occurs then no memory has been allocated,
+ * and *rrtname_r, *fmtname_r, *len_r and *data_r are undefined.
+ */
+
 const char *adns_strerror(adns_status st);
 
 #endif
index efad813..37edfa3 100644 (file)
@@ -48,7 +48,9 @@ void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
            bef,
            adns__diag_domain(qu->ads,-1,0, &vb,qu->flags,
                              qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
-           qu->typei ? qu->typei->name : "<unknown>");
+           qu->typei ? qu->typei->rrtname : "<unknown>");
+    if (qu->typei && qu->typei->fmtname)
+      fprintf(stderr,"(%s)",qu->typei->fmtname);
     bef=", "; aft=")\n";
   }
   
@@ -159,9 +161,79 @@ const char *adns__diag_domain(adns_state ads, int serv, adns_query qu, vbuf *vb,
   }
   return vb->buf;
 }
-    
+
+adns_status adns_rr_info(adns_rrtype type,
+                        const char **rrtname_r, const char **fmtname_r,
+                        int *len_r,
+                        const void *datap, char **data_r) {
+  const typeinfo *typei;
+  vbuf vb;
+  adns_status st;
+
+  typei= adns__findtype(type);
+  if (!typei) return adns_s_notimplemented;
+
+  if (rrtname_r) *rrtname_r= typei->rrtname;
+  if (fmtname_r) *fmtname_r= typei->fmtname;
+  if (len_r) *len_r= typei->rrsz;
+
+  if (!datap) return adns_s_ok;
+  
+  adns__vbuf_init(&vb);
+  st= typei->convstring(&vb,datap);
+  if (st) goto x_freevb;
+  if (!adns__vbuf_append(&vb,"",1)) { st= adns_s_nolocalmem; goto x_freevb; }
+  assert(strlen(vb.buf) == vb.used-1);
+  *data_r= realloc(vb.buf,vb.used);
+  if (!*data_r) *data_r= vb.buf;
+  return adns_s_ok;
+
+ x_freevb:
+  adns__vbuf_free(&vb);
+  return st;
+}
+
+#define SINFO(n,s) { adns_s_##n, s }
+
+static const struct sinfo {
+  adns_status st;
+  const char *string;
+} sinfos[]= {
+  SINFO(  ok,                "OK"                                    ),
+  SINFO(  timeout,           "Timed out"                             ),
+  SINFO(  nolocalmem,        "Out of memory"                         ),
+  SINFO(  allservfail,       "No working nameservers"                ),
+  SINFO(  servfail,          "Nameserver failure"                    ),
+  SINFO(  notimplemented,    "Query not implemented"                 ),
+  SINFO(  refused,           "Refused by nameserver"                 ),
+  SINFO(  reasonunknown,     "Reason unknown"                        ),
+  SINFO(  norecurse,         "Recursion denied by nameserver"        ),
+  SINFO(  serverfaulty,      "Nameserver sent bad data"              ),
+  SINFO(  unknownreply,      "Reply from nameserver not understood"  ),
+  SINFO(  invaliddata,       "Invalid data"                          ),
+  SINFO(  inconsistent,      "Inconsistent data"                     ),
+  SINFO(  cname,             "RR refers to an alias"                 ),
+  SINFO(  nxdomain,          "No such domain"                        ),
+  SINFO(  nodata,            "No such data"                          ),
+  SINFO(  invaliddomain,     "Domain syntactically invalid"          ),
+  SINFO(  domaintoolong,     "Domain name too long"                  )
+};
+
+static int si_compar(const void *key, const void *elem) {
+  const adns_status *st= key;
+  const struct sinfo *si= elem;
+
+  return *st < si->st ? -1 : *st > si->st ? 1 : 0;
+}
+
 const char *adns_strerror(adns_status st) {
   static char buf[100];
+
+  const struct sinfo *si;
+
+  si= bsearch(&st,sinfos,sizeof(sinfos)/sizeof(*si),sizeof(*si),si_compar);
+  if (si) return si->string;
+  
   snprintf(buf,sizeof(buf),"code %d",st);
   return buf;
 }
index 257953f..852c05c 100644 (file)
@@ -82,9 +82,21 @@ typedef union {
 
 typedef struct {
   adns_rrtype type;
-  const char *name;
+  const char *rrtname;
+  const char *fmtname;
   int rrsz;
 
+  void (*makefinal)(adns_query qu, void *data);
+  /* Change memory management of *data.
+   * Previously, used alloc_interim, now use alloc_final.
+   */
+
+  adns_status (*convstring)(vbuf *vb, const void *data);
+  /* Converts the RR data to a string representation in vbuf.
+   * vbuf will be appended to (it must have been initialised),
+   * and will not be null-terminated by convstring.
+   */
+
   adns_status (*parse)(adns_query qu, int serv,
                       const byte *dgram, int dglen, int cbyte, int max,
                       void *store_r);
@@ -96,11 +108,6 @@ typedef struct {
    * If there is an overrun which might indicate truncation, it should set
    * *rdstart to -1; otherwise it may set it to anything else positive.
    */
-
-  void (*makefinal)(adns_query qu, void *data);
-  /* Change memory management of *data.
-   * Previously, used alloc_interim, now use alloc_final.
-   */
 } typeinfo;
 
 typedef struct allocnode {
@@ -487,16 +494,16 @@ static inline int ctype_alpha(int c) {
 
 #define LIST_LINK_TAIL_PART(list,node,part) \
   do { \
-    (node)->part back= 0; \
-    (node)->part next= (list).tail; \
-    if ((list).tail) (list).tail->part back= (node); else (list).part head= (node); \
+    (node)->part next= 0; \
+    (node)->part back= (list).tail; \
+    if ((list).tail) (list).tail->part next= (node); else (list).part head= (node); \
     (list).tail= (node); \
   } while(0)
 
 #define LIST_UNLINK(list,node) LIST_UNLINK_PART(list,node,)
 #define LIST_LINK_TAIL(list,node) LIST_LINK_TAIL_PART(list,node,)
 
-#define GETIL_B(cb) (dgram[(cb)++])
+#define GETIL_B(cb) (((dgram)[(cb)++]) & 0x0ff)
 #define GET_B(cb,tv) ((tv)= GETIL_B((cb)))
 #define GET_W(cb,tv) ((tv)=0, (tv)|=(GETIL_B((cb))<<8), (tv)|=GETIL_B(cb), (tv))
 
index 099deb7..46d76fa 100644 (file)
@@ -63,25 +63,30 @@ void adns__findlabel_start(findlabel_state *fls, adns_state ads,
 
 adns_status adns__findlabel_next(findlabel_state *fls,
                                 int *lablen_r, int *labstart_r) {
-  int lablen, jumped;
+  int lablen, jumped, jumpto;
   const char *dgram;
 
   jumped= 0;
   dgram= fls->dgram;
   for (;;) {
-    if (fls->cbyte+2 > fls->dglen) goto x_truncated;
-    if (fls->cbyte+2 > fls->max) goto x_serverfaulty;
-    GET_W(fls->cbyte,lablen);
-    if (!(lablen & 0x0c000)) break;
-    if ((lablen & 0x0c000) != 0x0c000) return adns_s_unknownreply;
+    if (fls->cbyte >= fls->dglen) goto x_truncated;
+    if (fls->cbyte >= fls->max) goto x_serverfaulty;
+    GET_B(fls->cbyte,lablen);
+    if (!(lablen & 0x0c0)) break;
+    if ((lablen & 0x0c0) != 0x0c0) return adns_s_unknownreply;
     if (jumped++) {
       adns__diag(fls->ads,fls->serv,fls->qu,"compressed datagram contains loop");
       return adns_s_serverfaulty;
     }
+    if (fls->cbyte >= fls->dglen) goto x_truncated;
+    if (fls->cbyte >= fls->max) goto x_serverfaulty;
+    GET_B(fls->cbyte,jumpto);
+    jumpto |= (lablen&0x3f)<<8;
     if (fls->dmend_r) *(fls->dmend_r)= fls->cbyte;
-    fls->cbyte= DNS_HDRSIZE+(lablen&0x3fff);
+    fls->cbyte= jumpto;
     fls->dmend_r= 0; fls->max= fls->dglen+1;
   }
+  if (labstart_r) *labstart_r= fls->cbyte;
   if (lablen) {
     if (fls->namelen) fls->namelen++;
     fls->namelen+= lablen;
@@ -92,8 +97,8 @@ adns_status adns__findlabel_next(findlabel_state *fls,
   } else {
     if (fls->dmend_r) *(fls->dmend_r)= fls->cbyte;
   }
-  if (labstart_r) *labstart_r= fls->cbyte;
   *lablen_r= lablen;
+/*if (labstart_r) fprintf(stderr,"label %d >%.*s<\n",lablen,lablen,fls->dgram+*labstart_r);*/
   return adns_s_ok;
 
  x_truncated:
@@ -185,12 +190,13 @@ static adns_status findrr_intern(adns_query qu, int serv,
       st= adns__findlabel_next(&eo_fls,&eo_lablen,&eo_labstart);
       assert(!st); assert(eo_lablen>=0);
       if (lablen != eo_lablen) mismatch= 1;
-      while (!mismatch && lablen-- > 0) {
+      while (!mismatch && eo_lablen-- > 0) {
        ch= dgram[labstart++]; if (ctype_alpha(ch)) ch &= ~32;
        eo_ch= eo_dgram[eo_labstart++]; if (ctype_alpha(eo_ch)) eo_ch &= ~32;
        if (ch != eo_ch) mismatch= 1;
       }
     }
+    if (!lablen) break;
   }
   if (eo_matched_r) *eo_matched_r= !mismatch;
    
@@ -198,7 +204,7 @@ static adns_status findrr_intern(adns_query qu, int serv,
   GET_W(cbyte,tmp); *type_r= tmp;
   GET_W(cbyte,tmp); *class_r= tmp;
   cbyte+= 4; /* we skip the TTL */
-  GET_W(cbyte,rdlen); if (rdlen_r) *rdlen_r= tmp;
+  GET_W(cbyte,rdlen); if (rdlen_r) *rdlen_r= rdlen;
   if (rdstart_r) *rdstart_r= cbyte;
   cbyte+= rdlen;
   if (cbyte>dglen) goto x_truncated;
@@ -207,7 +213,7 @@ static adns_status findrr_intern(adns_query qu, int serv,
 
  x_truncated:
   *type_r= -1;
-  return 0;;
+  return 0;
 }
 
 adns_status adns__findrr(adns_query qu, int serv,
index f98540c..5ed6581 100644 (file)
 #include "internal.h"
 
 static void cname_recurse(adns_query qu, adns_queryflags xflags) {
-  abort(); /* FIXME */
+  assert(!"cname not implemented"); /* FIXME */
 }
     
 void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
                     int serv, struct timeval now) {
-  int cbyte, rrstart, wantedrrs, rri, foundsoa, foundns;
+  int cbyte, rrstart, wantedrrs, rri, foundsoa, foundns, cname_here;
   int id, f1, f2, qdcount, ancount, nscount, arcount;
   int flg_ra, flg_rd, flg_tc, flg_qr, opcode;
   int rrtype, rrclass, rdlength, rdstart, ownermatched, l;
@@ -36,6 +36,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
   adns_query qu, nqu;
   dns_rcode rcode;
   adns_status st;
+  vbuf tempvb;
   
   if (dglen<DNS_HDRSIZE) {
     adns__diag(ads,serv,0,"received datagram too short for message header (%d)",dglen);
@@ -56,11 +57,10 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
   flg_tc= f1&0x20;
   flg_rd= f1&0x01;
   flg_ra= f2&0x80;
-  rcode= (f1&0x0f);
-  /* fixme: change this to f2 (which is where rcode really is), BUT
-   * not until we've figured out why the error code is wrong (bad format code 203)
-   */
+  rcode= (f2&0x0f);
 
+  cname_here= 0;
+  
   if (!flg_qr) {
     adns__diag(ads,serv,0,"server sent us a query, not a response");
     return;
@@ -87,11 +87,17 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
       continue;
     break;
   }
-  anstart= qu->query_dglen;
   if (!qu) {
-    adns__debug(ads,serv,0,"reply not found (id=%02x)",id);
+    if (ads->iflags & adns_if_debug) {
+      adns__vbuf_init(&tempvb);
+      adns__debug(ads,serv,0,"reply not found, id %02x, query owner %s",
+                 id, adns__diag_domain(ads,serv,0,&tempvb,adns_qf_anyquote,
+                                       dgram,dglen,DNS_HDRSIZE));
+      adns__vbuf_free(&tempvb);
+    }
     return;
   }
+  anstart= qu->query_dglen;
 
   LIST_UNLINK(ads->timew,qu);
   /* We're definitely going to do something with this query now */
@@ -125,12 +131,13 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
    * If it has any CNAMEs we stuff them in the answer.
    */
   wantedrrs= 0;
+  cbyte= anstart;
   for (rri= 0; rri<ancount; rri++) {
     rrstart= cbyte;
     st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
                     &rrtype,&rrclass,&rdlength,&rdstart,
                     &ownermatched);
-    if (st) adns__query_fail(qu,st);
+    if (st) { adns__query_fail(qu,st); return; }
     if (rrtype == -1) goto x_truncated;
 
     if (rrclass != DNS_CLASS_IN) {
@@ -161,6 +168,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
        qu->answer->cname= adns__alloc_interim(qu,l);
        if (!qu->answer->cname) return;
        memcpy(qu->answer->cname,qu->vb.buf,l);
+       cname_here= 1;
        /* If we find the answer section truncated after this point we restart
         * the query at the CNAME; if beforehand then we obviously have to use
         * TCP.  If there is no truncation we can use the whole answer if
@@ -219,7 +227,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
      * a CNAME in this datagram then we should probably do our own CNAME
      * lookup now in the hope that we won't get a referral again.
      */
-    if (qu->cname_dgram == dgram) { cname_recurse(qu,0); return; }
+    if (cname_here) { cname_recurse(qu,0); return; }
 
     /* Bloody hell, I thought we asked for recursion ? */
     if (flg_rd) {
@@ -257,6 +265,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
                         qu->answer->rrs.bytes+qu->answer->nrrs*qu->typei->rrsz);
     if (st) { adns__query_fail(qu,st); return; }
     if (rdstart==-1) goto x_truncated;
+    qu->answer->nrrs++;
   }
 
   /* This may have generated some child queries ... */
index 5219ff5..436cc87 100644 (file)
  *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
  */
 
+#include <arpa/inet.h>
+
 #include "internal.h"
 
-static adns_status rp_inaddr(adns_query qu, int serv,
+static adns_status pa_inaddr(adns_query qu, int serv,
                             const byte *dgram, int dglen, int cbyte, int max,
                             void *store_r) {
   struct in_addr *dr= store_r;
@@ -32,13 +34,25 @@ static adns_status rp_inaddr(adns_query qu, int serv,
   return adns_s_ok;
 }
 
-static void rmf_null(adns_query qu, void *data) { }
+static adns_status cs_inaddr(vbuf *vb, const void *data) {
+  const struct in_addr *dp= data;
+  const char *ia;
+
+  ia= inet_ntoa(*dp); assert(ia);
+  return adns__vbuf_appendstr(vb,ia) ? adns_s_ok : adns_s_nolocalmem;
+}
 
-#define TYPE_SF(size,func,free)    size, rp_##func, rmf_##free
-#define TYPE_SN(size,func)         size, rp_##func, rmf_null
+static void fr_null(adns_query qu, void *data) { }
+
+#define TYPE_SF(size,func,cp,free) size, pa_##func, fr_##free, cs_##cp
+#define TYPE_SN(size,func,cp)      size, pa_##func, fr_null, cs_##cp
 #define TYPESZ_M(member)           (sizeof(((adns_answer*)0)->rrs.member))
-#define TYPE_MF(member,parse)      TYPE_SF(TYPESZ_M(member),parse,member)
-#define TYPE_MN(member,parse)      TYPE_SN(TYPESZ_M(member),parse)
+#define TYPE_MF(memb,parse)        TYPE_SF(TYPESZ_M(memb),parse,memb,memb)
+#define TYPE_MN(memb,parse)        TYPE_SN(TYPESZ_M(memb),parse,memb)
+
+#define DEEP_MEMB(memb) TYPESZ_M(memb), fr_##memb, cs_##memb
+#define FLAT_MEMB(memb) TYPESZ_M(memb), fr_null, cs_##memb
+#define NULL_MEMB       0, fr_null, cs_null
 
 /* TYPE_<ms><nf>
  *  ms is M  specify member name
@@ -49,26 +63,26 @@ static void rmf_null(adns_query qu, void *data) { }
 
 static const typeinfo typeinfos[] = {
   /* Must be in ascending order of rrtype ! */
-  /* rr type code     name             style     member     size  parser */
+  /* rr type code   rrt     fmt        mem.mgmt  member      parser        */
   
-  {  adns_r_a,        "A",             TYPE_MN(  inaddr,          inaddr       ) },
-#if 0 /*fixme*/                                               
-  {  adns_r_ns_raw,   "NS(raw)",       TYPE_MF(  str,             domain_raw   ) },
-  {  adns_r_cname,    "CNAME",         TYPE_MF(  str,             domain_raw   ) },
-  {  adns_r_soa_raw,  "SOA(raw)",      TYPE_MF(  soa,             soa          ) },
-  {  adns_r_null,     "NULL",          TYPE_SN(              0,   null         ) },
-  {  adns_r_ptr_raw,  "PTR(raw)",      TYPE_MF(  str,             domain_raw   ) },
-  {  adns_r_hinfo,    "HINFO",         TYPE_MF(  strpair,         hinfo        ) },
-  {  adns_r_mx_raw,   "MX(raw)",       TYPE_MF(  intstr,          mx_raw       ) },
-  {  adns_r_txt,      "TXT",           TYPE_MF(  str,             txt          ) },
-  {  adns_r_rp_raw,   "RP(raw)",       TYPE_MF(  strpair,         rp           ) },
-                                                             
-  {  adns_r_ns,       "NS(+addr)",     TYPE_MF(  dmaddr,          dmaddr       ) },
-  {  adns_r_ptr,      "PTR(checked)",  TYPE_MF(  str,             ptr          ) },
-  {  adns_r_mx,       "MX(+addr)",     TYPE_MF(  intdmaddr,       mx           ) },
-                                                             
-  {  adns_r_soa,      "SOA(822)",      TYPE_MF(  soa,             soa          ) },
-  {  adns_r_rp,       "RP(822)",       TYPE_MF(  strpair,         rp           ) },
+  { adns_r_a,       "A",     0,        FLAT_MEMB(inaddr),    pa_inaddr      },
+#if 0 /*fixme*/                                                                   
+  { adns_r_ns_raw,  "NS",   "raw",     DEEP_MEMB(str),       pa_domain_raw  },
+  { adns_r_cname,   "CNAME", 0,        DEEP_MEMB(str),       pa_domain_raw  },
+  { adns_r_soa_raw, "SOA",  "raw",     DEEP_MEMB(soa),       pa_soa         },
+  { adns_r_null,    "NULL",  0,        NULL_MEMB,            pa_null        },
+  { adns_r_ptr_raw, "PTR",  "raw",     DEEP_MEMB(str),       pa_domain_raw  },
+  { adns_r_hinfo,   "HINFO", 0,        DEEP_MEMB(strpair),   pa_hinfo       },
+  { adns_r_mx_raw,  "MX",   "raw",     DEEP_MEMB(intstr),    pa_mx_raw      },
+  { adns_r_txt,     "TXT",   0,        DEEP_MEMB(str),       pa_txt         },
+  { adns_r_rp_raw,  "RP",   "raw",     DEEP_MEMB(strpair),   pa_rp          },
+                                                                          
+  { adns_r_ns,      "NS",   "+addr",   DEEP_MEMB(dmaddr),    pa_dmaddr      },
+  { adns_r_ptr,     "PTR",  "checked", DEEP_MEMB(str),       pa_ptr         },
+  { adns_r_mx,      "MX",   "+addr",   DEEP_MEMB(intdmaddr), pa_mx          },
+                                                                          
+  { adns_r_soa,     "SOA",  "822",     DEEP_MEMB(soa),       pa_soa         },
+  { adns_r_rp,      "RP",   "822",     DEEP_MEMB(strpair),   pa_rp          },
 #endif
 };