chiark / gitweb /
src/: Lay the groundwork for variably-sized record structures.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 31 May 2014 23:13:20 +0000 (00:13 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Fri, 13 Jun 2014 08:57:41 +0000 (09:57 +0100)
All records in a particular answer are going to be the same size: that's
not going to change.  The case we're dealing with here is that we're
going to want to include new information (e.g., new kinds of address
families) which will make the structures larger -- and would break old
binary clients.

The plan is for new clients to encode a flag saying that they understand
the extended structure in the type field (implicitly, through a header-
file change).  But all of this means that just dredging `typei->rrsz'
out of the typeinfo structure isn't going to cut it any more, so we add
a type hook to compute the right size, and make sure that we use it by
renaming the slot containing the fixed value.  Most places in the code
can avoid having to call the hook by grabbing the record size from the
answer structure.

This involves adding an extra parameter to the postsort hook, which
otherwise might not be able to determine the right size for itself.

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

index 4404b31109191d4754f65246beb654bd2324fee4..6ef2cb316213e17b2cf068f00659e459ea0c92c2 100644 (file)
@@ -196,6 +196,9 @@ const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
   return vb->buf;
 }
 
+int adns__getrrsz_default(const typeinfo *typei, adns_rrtype type)
+  { return typei->fixed_rrsz; }
+
 adns_status adns_rr_info(adns_rrtype type,
                         const char **rrtname_r, const char **fmtname_r,
                         int *len_r,
@@ -209,7 +212,7 @@ adns_status adns_rr_info(adns_rrtype type,
 
   if (rrtname_r) *rrtname_r= typei->rrtname;
   if (fmtname_r) *fmtname_r= typei->fmtname;
-  if (len_r) *len_r= typei->rrsz;
+  if (len_r) *len_r= typei->getrrsz(typei, type);
 
   if (!datap) return adns_s_ok;
   
index 29f4dd23e7735c077ee8f02323f4e5ab8f95bf3f..7ad6daa0d8a10612e4448155e4c405be29ae7e6f 100644 (file)
@@ -148,7 +148,7 @@ typedef struct typeinfo {
   adns_rrtype typekey;
   const char *rrtname;
   const char *fmtname;
-  int rrsz;
+  int fixed_rrsz;
 
   void (*makefinal)(adns_query qu, void *data);
   /* Change memory management of *data.
@@ -166,7 +166,7 @@ typedef struct typeinfo {
   /* Parse one RR, in dgram of length dglen, starting at cbyte and
    * extending until at most max.
    *
-   * The RR should be stored at *store_r, of length qu->typei->rrsz.
+   * The RR should be stored at *store_r, of length qu->typei->getrrsz().
    *
    * If there is an overrun which might indicate truncation, it should set
    * *rdstart to -1; otherwise it may set it to anything else positive.
@@ -191,12 +191,17 @@ typedef struct typeinfo {
    * because lablen is zero.
    */
 
-  void (*postsort)(adns_state ads, void *array, int nrrs,
+  void (*postsort)(adns_state ads, void *array, int nrrs,int rrsz,
                   const struct typeinfo *typei);
   /* Called immediately after the RRs have been sorted, and may rearrange
    * them.  (This is really for the benefit of SRV's bizarre weighting
    * stuff.)  May be 0 to mean nothing needs to be done.
    */
+
+  int (*getrrsz)(const struct typeinfo *typei, adns_rrtype type);
+  /* Return the output resource-record element size; if this is null, then
+   * the rrsz member can be used.
+   */
 } typeinfo;
 
 adns_status adns__ckl_hostname(adns_state ads, adns_queryflags flags,
@@ -405,6 +410,11 @@ const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
  * vb before using the return value.
  */
 
+int adns__getrrsz_default(const typeinfo *typei, adns_rrtype type);
+/* Default function for the `getrrsz' type hook; returns the `fixed_rrsz'
+ * value from the typeinfo entry.
+ */
+
 void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
                 int (*needswap)(void *context, const void *a, const void *b),
                 void *context);
index 541d8ac35d11fc40d69e6195bf41079b2962f5db..717cac0d3c7418b3e751c04d65b4dfba29de09f5 100644 (file)
@@ -83,7 +83,7 @@ static adns_query query_alloc(adns_state ads,
   qu->answer->expires= -1;
   qu->answer->nrrs= 0;
   qu->answer->rrs.untyped= 0;
-  qu->answer->rrsz= typei->rrsz;
+  qu->answer->rrsz= typei->getrrsz(typei,type);
 
   return qu;
 }
@@ -580,7 +580,7 @@ void adns__query_done(adns_query qu) {
   }
 
   if (ans->nrrs && qu->typei->diff_needswap) {
-    if (!adns__vbuf_ensure(&qu->vb,qu->typei->rrsz)) {
+    if (!adns__vbuf_ensure(&qu->vb,qu->answer->rrsz)) {
       adns__query_fail(qu,adns_s_nomemory);
       return;
     }
@@ -591,7 +591,8 @@ void adns__query_done(adns_query qu) {
                qu->ads);
   }
   if (ans->nrrs && qu->typei->postsort) {
-    qu->typei->postsort(qu->ads, ans->rrs.bytes, ans->nrrs, qu->typei);
+    qu->typei->postsort(qu->ads, ans->rrs.bytes,
+                       ans->nrrs,ans->rrsz, qu->typei);
   }
 
   ans->expires= qu->expires;
index 62384ab9571d70c3b7d25e850e3ae5836a974ad9..08d274f775e0b09b3c51d6d9891bc8249f64e9fe 100644 (file)
@@ -311,7 +311,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
 
   /* Now, we have some RRs which we wanted. */
 
-  qu->answer->rrs.untyped= adns__alloc_interim(qu,qu->typei->rrsz*wantedrrs);
+  qu->answer->rrs.untyped= adns__alloc_interim(qu,qu->answer->rrsz*wantedrrs);
   if (!qu->answer->rrs.untyped) {
     adns__query_fail(qu,adns_s_nomemory);
     return;
@@ -341,7 +341,8 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
        !ownermatched)
       continue;
     adns__update_expires(qu,ttl,now);
-    st= typei->parse(&pai, rdstart,rdstart+rdlength, rrsdata+nrrs*typei->rrsz);
+    st= typei->parse(&pai, rdstart,rdstart+rdlength,
+                    rrsdata+nrrs*qu->answer->rrsz);
     if (st) { adns__query_fail(qu,st); return; }
     if (rdstart==-1) goto x_truncated;
     nrrs++;
index 90413a0bd4a2d98849a0094b97d7e16ae6a439b8..f4a25391aef2cf45ec7dd7ac641c88d5bf7ab22a 100644 (file)
@@ -1100,12 +1100,12 @@ static adns_status cs_srvha(vbuf *vb, const void *datap) {
   return csp_hostaddr(vb,&rrp->ha);
 }
 
-static void postsort_srv(adns_state ads, void *array, int nrrs,
+static void postsort_srv(adns_state ads, void *array, int nrrs,int rrsz,
                         const struct typeinfo *typei) {
   /* we treat everything in the array as if it were an adns_rr_srvha
    * even though the array might be of adns_rr_srvraw.  That's OK
    * because they have the same prefix, which is all we access.
-   * We use typei->rrsz, too, rather than naive array indexing, of course.
+   * We use rrsz, too, rather than naive array indexing, of course.
    */
   char *workbegin, *workend, *search, *arrayend;
   const adns_rr_srvha *rr;
@@ -1113,14 +1113,15 @@ static void postsort_srv(adns_state ads, void *array, int nrrs,
   int cpriority, totalweight, runtotal;
   long randval;
 
-  for (workbegin= array, arrayend= workbegin + typei->rrsz * nrrs;
+  assert(rrsz <= sizeof(rrtmp));
+  for (workbegin= array, arrayend= workbegin + rrsz * nrrs;
        workbegin < arrayend;
        workbegin= workend) {
     cpriority= (rr=(void*)workbegin)->priority;
     
     for (workend= workbegin, totalweight= 0;
         workend < arrayend && (rr=(void*)workend)->priority == cpriority;
-        workend += typei->rrsz) {
+        workend += rrsz) {
       totalweight += rr->weight;
     }
 
@@ -1131,8 +1132,8 @@ static void postsort_srv(adns_state ads, void *array, int nrrs,
      * workbegin (swapping with the one that was there, and then
      * advance workbegin. */
     for (;
-        workbegin + typei->rrsz < workend; /* don't bother if just one */
-        workbegin += typei->rrsz) {
+        workbegin + rrsz < workend; /* don't bother if just one */
+        workbegin += rrsz) {
       
       randval= nrand48(ads->rand48xsubi);
       randval %= (totalweight + 1);
@@ -1144,13 +1145,13 @@ static void postsort_srv(adns_state ads, void *array, int nrrs,
 
       for (search=workbegin, runtotal=0;
           (runtotal += (rr=(void*)search)->weight) < randval;
-          search += typei->rrsz);
+          search += rrsz);
       assert(search < arrayend);
       totalweight -= rr->weight;
       if (search != workbegin) {
-       memcpy(&rrtmp, workbegin, typei->rrsz);
-       memcpy(workbegin, search, typei->rrsz);
-       memcpy(search, &rrtmp, typei->rrsz);
+       memcpy(&rrtmp, workbegin, rrsz);
+       memcpy(workbegin, search, rrsz);
+       memcpy(search, &rrtmp, rrsz);
       }
     }
   }
@@ -1226,11 +1227,11 @@ static void mf_flat(adns_query qu, void *data) { }
 #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__) }
+     adns__ckl_hostname, 0, adns__getrrsz_default, 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__) }
+     adns__ckl_hostname, 0, adns__getrrsz_default, CDR(__VA_ARGS__) }
 
 #define di_0 0