chiark / gitweb /
src/: Carve out a `representation' subfield of adns_rrtype.
[adns.git] / src / types.c
index 8bc7155a311f3759919e3b21f54a55946a6e895a..83a57927ad9f74f019240ec564a5c5490561af68 100644 (file)
  * _mx                        (pa,di)
  * _inthostaddr               (mf,cs)
  * _inthost                  (cs)
- * _ptr                       (pa)
+ * _ptr                       (ckl,pa +icb_ptr)
  * _strpair                   (mf)
  * _intstrpair                (mf)
  * _hinfo                     (pa)
  * _mailbox                   (pap,csp +pap_mailbox822)
  * _rp                        (pa,cs)
  * _soa                       (pa,mf,cs)
- * _srv*                      (qdpl,(pap),pa*2,mf*2,di,(csp),cs*2,postsort)
+ * _srv*                      (ckl,(pap),pa*2,mf*2,di,(csp),cs*2,postsort)
  * _byteblock                 (mf)
  * _opaque                    (pa,cs)
  * _flat                      (mf)
  *
  * within each section:
- *    qdpl_*
+ *    ckl_*
  *    pap_*
  *    pa_*
  *    dip_*
@@ -704,12 +704,42 @@ 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 };
+  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;
+    ctx->tinfo.ptr.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;
+  const struct in_addr *queried;
+  const unsigned char *found;
   adns_state ads= parent->ads;
   int i;
 
@@ -721,10 +751,9 @@ static void icb_ptr(adns_query parent, adns_query child) {
     return;
   }
 
-  queried= &parent->ctx.tinfo.ptr_addr;
-  for (i=0, found=cans->rrs.addr; i<cans->nrrs; i++, found++) {
-    if (queried->len == found->len &&
-       !memcmp(&queried->addr,&found->addr,queried->len)) {
+  queried= &parent->ctx.tinfo.ptr.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) {
        adns__query_done(parent);
        return;
@@ -740,16 +769,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,48 +781,16 @@ 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);
+                           adns_r_a, adns_qf_quoteok_query);
   if (st) return st;
 
   ctx.ext= 0;
   ctx.callback= icb_ptr;
   memset(&ctx.pinfo,0,sizeof(ctx.pinfo));
   memset(&ctx.tinfo,0,sizeof(ctx.tinfo));
-  st= adns__internal_submit(pai->ads, &nqu, adns__findtype(adns_r_addr),
+  st= adns__internal_submit(pai->ads, &nqu, adns__findtype(adns_r_a),
                            &pai->qu->vb, id,
                            adns_qf_quoteok_query, pai->now, &ctx);
   if (st) return st;
@@ -1010,36 +1000,17 @@ static adns_status cs_soa(vbuf *vb, const void *datap) {
 }
 
 /*
- * _srv*  (qdpl,(pap),pa*2,mf*2,di,(csp),cs*2,postsort)
+ * _srv*  (ckl,(pap),pa*2,mf*2,di,(csp),cs*2,postsort)
  */
 
-static adns_status qdpl_srv(adns_state ads,
-                           const char **p_io, const char *pe, int labelnum,
-                           char label_r[DNS_MAXDOMAIN], int *ll_io,
-                           adns_queryflags flags,
-                           const typeinfo *typei) {
-  int useflags;
-  const char *p_orig;
-  adns_status st;
-
-  if (labelnum < 2 && !(flags & adns_qf_quoteok_query)) {
-    useflags= adns_qf_quoteok_query;
-    p_orig= *p_io;
-  } else {
-    useflags= flags;
-    p_orig= 0;
-  }
-  st= adns__qdpl_normal(ads, p_io,pe, labelnum,label_r, ll_io, useflags,typei);
-  if (st) return st;
-
-  if (p_orig) {
-    int ll= *ll_io;
-    if (!ll || label_r[0]!='_')
-      return adns_s_querydomaininvalid;
-    if (memchr(p_orig+1, '\\', pe - (p_orig+1)))
-      return adns_s_querydomaininvalid;
+static adns_status ckl_srv(adns_state ads, adns_queryflags flags,
+                          union checklabel_state *cls, qcontext *ctx,
+                          int labnum, const char *label, int lablen) {
+  if (labnum < 2 && !(flags & adns_qf_quoteok_query)) {
+    if (!lablen || label[0] != '_') return adns_s_querydomaininvalid;
+    return adns_s_ok;
   }
-  return adns_s_ok;
+  return adns__ckl_hostname(ads, flags, cls, ctx, labnum, label, lablen);
 }
 
 static adns_status pap_srv_begin(const parseinfo *pai, int *cbyte_io, int max,
@@ -1250,50 +1221,53 @@ static void mf_flat(adns_query qu, void *data) { }
 
 #define TYPESZ_M(member)           (sizeof(*((adns_answer*)0)->rrs.member))
 
-#define DEEP_TYPE(code,rrt,fmt,memb,parser,comparer,printer)   \
- { adns_r_##code, rrt,fmt,TYPESZ_M(memb), mf_##memb,           \
-      printer,parser,comparer, adns__qdpl_normal,0 }
-#define FLAT_TYPE(code,rrt,fmt,memb,parser,comparer,printer)   \
- { adns_r_##code, rrt,fmt,TYPESZ_M(memb), mf_flat,             \
-     printer,parser,comparer, adns__qdpl_normal,0 }
-#define XTRA_TYPE(code,rrt,fmt,memb,parser,comparer,printer,qdpl,postsort) \
- { adns_r_##code, rrt,fmt,TYPESZ_M(memb), mf_##memb,                      \
-    printer,parser,comparer,qdpl,postsort }
+#define DEEP_TYPE(code,rrt,fmt,memb,parser,comparer,/*printer*/...)    \
+ { adns_r_##code&adns_rrt_reprmask, rrt,fmt,TYPESZ_M(memb), mf_##memb, \
+     GLUE(cs_, CAR(__VA_ARGS__)),pa_##parser,di_##comparer,            \
+     adns__ckl_hostname, CDR(__VA_ARGS__) }
+#define FLAT_TYPE(code,rrt,fmt,memb,parser,comparer,/*printer*/...)    \
+ { adns_r_##code&adns_rrt_reprmask, rrt,fmt,TYPESZ_M(memb), mf_flat,   \
+     GLUE(cs_, CAR(__VA_ARGS__)),pa_##parser,di_##comparer,            \
+     adns__ckl_hostname, CDR(__VA_ARGS__) }
+
+#define di_0 0
 
 static const typeinfo typeinfos[] = {
 /* Must be in ascending order of rrtype ! */
 /* mem-mgmt code  rrt     fmt   member   parser      comparer  printer */
 
-FLAT_TYPE(a,      "A",     0,   inaddr,  pa_inaddr,  di_inaddr,cs_inaddr     ),
-DEEP_TYPE(ns_raw, "NS",   "raw",str,     pa_host_raw,0,        cs_domain     ),
-DEEP_TYPE(cname,  "CNAME", 0,   str,     pa_dom_raw, 0,        cs_domain     ),
-DEEP_TYPE(soa_raw,"SOA",  "raw",soa,     pa_soa,     0,        cs_soa        ),
-DEEP_TYPE(ptr_raw,"PTR",  "raw",str,     pa_host_raw,0,        cs_domain     ),
-DEEP_TYPE(hinfo,  "HINFO", 0, intstrpair,pa_hinfo,   0,        cs_hinfo      ),
-DEEP_TYPE(mx_raw, "MX",   "raw",intstr,  pa_mx_raw,  di_mx_raw,cs_inthost    ),
-DEEP_TYPE(txt,    "TXT",   0,   manyistr,pa_txt,     0,        cs_txt        ),
-DEEP_TYPE(rp_raw, "RP",   "raw",strpair, pa_rp,      0,        cs_rp         ),
-XTRA_TYPE(srv_raw,"SRV",  "raw",srvraw , pa_srvraw,  di_srv,   cs_srvraw,
-                                                      qdpl_srv, postsort_srv),
-
-FLAT_TYPE(addr,   "A",  "addr", addr,    pa_addr,    di_addr,  cs_addr       ),
-DEEP_TYPE(ns,     "NS", "+addr",hostaddr,pa_hostaddr,di_hostaddr,cs_hostaddr ),
-DEEP_TYPE(ptr,    "PTR","checked",str,   pa_ptr,     0,        cs_domain     ),
-DEEP_TYPE(mx,     "MX", "+addr",inthostaddr,pa_mx,   di_mx,    cs_inthostaddr),
-XTRA_TYPE(srv,    "SRV","+addr",srvha,   pa_srvha,   di_srv,   cs_srvha,
-                                                      qdpl_srv, postsort_srv),
-
-DEEP_TYPE(soa,    "SOA","822",  soa,     pa_soa,     0,        cs_soa        ),
-DEEP_TYPE(rp,     "RP", "822",  strpair, pa_rp,      0,        cs_rp         ),
+FLAT_TYPE(a,      "A",     0,   inaddr,    inaddr,  inaddr,inaddr          ),
+DEEP_TYPE(ns_raw, "NS",   "raw",str,       host_raw,0,     domain          ),
+DEEP_TYPE(cname,  "CNAME", 0,   str,       dom_raw, 0,     domain          ),
+DEEP_TYPE(soa_raw,"SOA",  "raw",soa,       soa,     0,     soa             ),
+DEEP_TYPE(ptr_raw,"PTR",  "raw",str,       host_raw,0,     domain          ),
+DEEP_TYPE(hinfo,  "HINFO", 0,   intstrpair,hinfo,   0,     hinfo           ),
+DEEP_TYPE(mx_raw, "MX",   "raw",intstr,    mx_raw,  mx_raw,inthost         ),
+DEEP_TYPE(txt,    "TXT",   0,   manyistr,  txt,     0,     txt             ),
+DEEP_TYPE(rp_raw, "RP",   "raw",strpair,   rp,      0,     rp              ),
+DEEP_TYPE(srv_raw,"SRV",  "raw",srvraw ,   srvraw,  srv,   srvraw,
+                             .checklabel= ckl_srv, .postsort= postsort_srv),
+
+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,
+                                                      .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),
+
+DEEP_TYPE(soa,    "SOA","822",  soa,       soa,     0,     soa             ),
+DEEP_TYPE(rp,     "RP", "822",  strpair,   rp,      0,     rp              ),
 };
 
 static const typeinfo typeinfo_unknown=
-DEEP_TYPE(unknown,0, "unknown",byteblock,pa_opaque,  0,        cs_opaque     );
+DEEP_TYPE(unknown,0, "unknown",byteblock,opaque,  0,     opaque            );
 
 const typeinfo *adns__findtype(adns_rrtype type) {
   const typeinfo *begin, *end, *mid;
 
   if (type & adns_r_unknown) return &typeinfo_unknown;
+  type &= adns_rrt_reprmask;
 
   begin= typeinfos;  end= typeinfos+(sizeof(typeinfos)/sizeof(typeinfo));