chiark / gitweb /
WIP DNS bitenc test compiles
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 1 Aug 2011 11:33:09 +0000 (12:33 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 27 Aug 2011 15:44:05 +0000 (16:44 +0100)
Makefile.in
dns-bitenc-test.c
dns-transp-common.c
dns-transp-common.h

index e82baf6ce07fc939ad33493f56469a300f3e0bc4..0d1ff1aab78f7f40495f9a07ad5ecaefe1175ea1 100644 (file)
@@ -134,6 +134,9 @@ conffile.tab.c:     conffile.y
 secnet:        $(OBJECTS)
        $(CC) $(LDFLAGS) $(ALL_CFLAGS) -o $@ $(OBJECTS) $(LDLIBS)
 
+dns-bitenc-test: dns-bitenc-test.o dns-transp-common.c
+       $(CC) $(LDFLAGS) $(ALL_CFLAGS) -o $@ $^ $(LDLIBS)
+
 version.c: Makefile
        echo "#include \"secnet.h\"" >$@.new
        echo "char version[]=\"secnet $(VERSION)\";" >>$@.new
index 5d09cfb4ec8cb205c50a41ff0433424a362a673e..a11ecd9b37144b9489afc6e187a08a0843e03d55 100644 (file)
@@ -1,37 +1,50 @@
+/*
+ * Simple test program
+ */
+
+#include "dns-transp-common.h"
+
+#include <stdio.h>
+#include <inttypes.h>
+
 #define NMYLABELS 3
 static const char *const mylabels[NMYLABELS]={"z","example","com"};
 static const char prefix[]="PREFIX ";
 static const char suffix[]=" SUFFIX";
 static uint8_t packet[100];
 
-static struct dnsbitenc enc;
+static struct dnsdomainenc enc;
+static struct dnsdomaindec dec;
 
 int main(int argc, const char **argv) {
-    const char **argv_save=
+    dnsdomaindec_globalinit();
+
+    const char **argv_save=argv;
     memcpy(packet+sizeof(packet)-sizeof(suffix), suffix, sizeof(suffix));
-    dnsbitenc_start(&enc, packet+sizeof(prefix),
-                   sizeof(packet)-sizeof(prefix)-sizeof(suffix));
+    dnsdomainenc_start(&enc, packet+sizeof(prefix),
+                      sizeof(packet)-sizeof(prefix)-sizeof(suffix),
+                      NMYLABELS,mylabels);
     for (;;) {
        const char *arg = *++argv;
        if (!strcmp(arg,"b")) {
-           uint32_t val=strtoul(*++argv,0,0);
            int bits=atoi(*++argv);
-           dnsbitenc_addbits(&enc,val,bits);
+           uint32_t val=strtoul(*++argv,0,0);
+           dnsdomainenc_addbits(&enc,val,bits);
        } else if (!strcmp(arg,"w")) {
            uint32_t val=strtoul(*++argv,0,0);
-           dnsbitenc_addu32(&enc,val);
+           dnsdomainenc_addu32(&enc,val);
        } else if (!strcmp(arg,"r")) {
            const char *rest=*++argv;
            int l=strlen(rest);
-           int nofit=dnsbitenc_restbytes(&enc,rest,l);
+           int nofit=dnsdomainenc_restbytes(&enc,(const uint8_t*)rest,l);
            printf("FIT %.*s|%.*s\n",l-nofit,rest,nofit,rest+l-nofit);
            break;
        } else {
            abort();
        }
     }
-    const uint8_t *encoded=dnsbitenc_getresult(&enc);
-    const uint8_t *pktbegin=encoded-sizeof(prefix);
+    uint8_t *encoded=dnsdomainenc_getresult(&enc);
+    uint8_t *pktbegin=encoded-sizeof(prefix);
     memcpy(pktbegin,prefix,sizeof(prefix));
 
     const uint8_t *pr;
@@ -39,10 +52,10 @@ int main(int argc, const char **argv) {
        printf("%02x",*pr);
     printf("\n");
 
-    uint8_t domainend;
-    int r=dnsbitdec_start(&dec, pktbegin, packet+sizeof(packet),
-                         pktbegin+sizeof(prefix), NMYLABELS,mylabels,
-                         &domainend);
+    const uint8_t *domainend;
+    int r=dnsdomaindec_start(&dec, pktbegin, packet+sizeof(packet),
+                            pktbegin+sizeof(prefix), NMYLABELS,mylabels,
+                            &domainend);
     if (r) {
        printf("DEC ERROR %d\n",r);
        return 0;
@@ -51,15 +64,19 @@ int main(int argc, const char **argv) {
     for (;;) {
        const char *arg = *++argv;
        if (!strcmp(arg,"b")) {
-           ++argv;
            int bits=atoi(*++argv);
-           uint32_t 
-
-           if (nofit)
-               
-           } else 
-
-       const int c0=*arg++;
-       switch (c0) {
-       case 'b':
-           
+           ++argv;
+           uint32_t val=dnsdomaindec_getbits(&dec,bits);
+           printf("b %d 0x%"PRIx32, bits, val);
+       } else if (!strcmp(arg,"w")) {
+           uint32_t val=dnsdomaindec_getu32(&dec);
+           printf("w 0x%"PRIx32, val);
+       } else if (!strcmp(arg,"r")) {
+           uint8_t rbuf[MAX_DOMAIN_BYTES];
+           int l=dnsdomaindec_restbytes(&dec,rbuf);
+           printf("r %.*s",l,rbuf);
+       } else {
+           abort();
+       }
+    }
+}
index 2505828f42331434fd968ac12134a7101969589f..1b8eb860809658c8cdce69fcd8d6ea8896a329b8 100644 (file)
@@ -1,13 +1,18 @@
+/**/
+
+#include "dns-transp-common.h"
+
+#define MAX_DATA_LABELS 4
 
 static const char out_table[32]="0123456789abcdefghijklmnopqrstuv";
 
-static inline int enoughinput(struct dnsbitenc *be) {
+static inline int enoughinput(struct dnsdomainenc *be) {
     return be->npending >= 5;
 }
-static inline void startlabel(struct dnsbitenc *be) {
+static inline void startlabel(struct dnsdomainenc *be) {
     be->labremain=63;
 }
-static inline void outputchar(struct dnsbitenc *be) {
+static inline void outputchar(struct dnsdomainenc *be) {
     /* there must be enough input and enough space */
     if (!be->labremain) {
        *--(be->out) = 63;
@@ -18,16 +23,28 @@ static inline void outputchar(struct dnsbitenc *be) {
     be->npending -= 5;
 }
 
-void dnsbitenc_start(struct dnsbitenc *be, uint8_t *buf, int buflen) {
+int dnsdomainenc_start(struct dnsdomainenc *be, uint8_t *buf, int buflen,
+                      int mydompathlen, const char *const mydompath[]) {
+    int i;
     assert(buflen>0);
     be->pending=0;
     be->npending=0;
     be->bufstop=buf+1;
     be->out=buf+buflen;
+    for (i=mydompathlen-1; i>=0; i++) {
+       const char *lab=mydompath[i];
+       int ll=strlen(lab);
+       if (ll>63) return FAKERCODE_MYDOMAINLABELTOOLONG;
+       if (be->out <= be->bufstop+ll+1) return FAKERCODE_MYDOMAINTOOLONG;
+       be->out -= ll;
+       memcpy(be->out, lab, ll);
+       *be->out -= ll;
+    }
     startlabel(be);
+    return 0;
 }
 
-void dnsbitenc_addbits(struct dnsbitenc *be, uint32_t val, int nbits) {
+void dnsdomainenc_addbits(struct dnsdomainenc *be, uint32_t val, int nbits) {
     assert(nbits<=28); /* otherwise pending might overflow */
     assert(!(val & ~(((uint32_t)1 << nbits)-1)));
     be->pending |= val << be->npending;
@@ -38,18 +55,19 @@ void dnsbitenc_addbits(struct dnsbitenc *be, uint32_t val, int nbits) {
     }
 }
 
-void dnsbitenc_addu32(struct dnsbitenc *be, uint32_t val) {
-    dnsbitenc_addbits(be, val & 0xffff, 16);
-    dnsbitenc_addbits(be, val >> 16,    16);
+void dnsdomainenc_addu32(struct dnsdomainenc *be, uint32_t val) {
+    dnsdomainenc_addbits(be, val & 0xffff, 16);
+    dnsdomainenc_addbits(be, val >> 16,    16);
 }
 
-int dnsbitenc_restbytes(struct dnsbitenc *be, uint8_t *bytes, int qty) {
+int dnsdomainenc_restbytes(struct dnsdomainenc *be,
+                          const uint8_t *bytes, int avail) {
     for (;;) {
-       if (buf==bufstop) {
-           return qty + ((be->npending + 7) / 8);
+       if (be->out == be->bufstop) {
+           return avail + ((be->npending + 7) / 8);
        }
        if (be->npending<5) {
-           if (qty) {
+           if (avail) {
                be->pending |= (*bytes++) << be->npending;
                be->npending += 8;
            } else if (be->npending <= 0) {
@@ -60,44 +78,50 @@ int dnsbitenc_restbytes(struct dnsbitenc *be, uint8_t *bytes, int qty) {
     }
 }
 
-uint8_t *dnsbitenc_getresult(struct dnsbitenc *be) {
+uint8_t *dnsdomainenc_getresult(struct dnsdomainenc *be) {
     *--(be->out) = 63 - be->labremain; /* finish the last label */
     return be->out;
 }
 
 
 
+static uint8_t in_table[256];
+
+void dnsdomaindec_globalinit(void) {
+    int i;
+    memset(in_table,0xff,sizeof(in_table));
+    for (i=0; i<32; i++) {
+       in_table[(uint8_t)out_table[i]]=i;
+       in_table[toupper((unsigned char)out_table[i])]=i;
+    }
+}
 
-#define MAX_DATA_LABELS
 
 struct labelinpacket {
     const uint8_t *bytes;
     int len;
 };
 
-struct dnsbitdec {
-    /* private for dnsbitdec_... functions; do not access direcctly */
-    const databuf[MAX_DOMAIN_BYTES];
-    const uint8_t *in;
-};
-
 static void setafter(const uint8_t *domain, const uint8_t **domain_end_r) {
     if (domain_end_r && !*domain_end_r)
        *domain_end_r=domain;
 }
 
-int dnsdomaindec_start(struct dnsbitdec *bd, const uint8_t *packet,
+int dnsdomaindec_start(struct dnsdomaindec *bd, const uint8_t *packet,
                       const uint8_t *endpacket, const uint8_t *domain,
-                      int mydompathlen, const char *mydompath[],
+                      int mydompathlen, const char *const mydompath[],
                       const uint8_t **domain_end_r) {
-    int maxlabels=mydompath+MAX_DATA_LABELS;
-    const strut labelinpacket labels[maxlabels];
-    int nlabels=0, totallen=0;
+    int maxlabels=mydompathlen+MAX_DATA_LABELS;
+    struct labelinpacket labels[maxlabels];
+    int nlabels=0, totallen=0, i, j;
+
+    bd->pending=0;
+    bd->npending=0;
 
     *domain_end_r=0;
     for (;;) {
        if (domain==endpacket)
-           return FORMERR;
+           return RCODE_FORMERR;
        unsigned b=*domain++;
        if (!b) {
            totallen++;
@@ -106,46 +130,46 @@ int dnsdomaindec_start(struct dnsbitdec *bd, const uint8_t *packet,
        }
        if ((b & 0xc0) == 0xc0) {
            if (domain==endpacket)
-               return FORMERR;
+               return RCODE_FORMERR;
            unsigned b2=*domain++;
            setafter(domain,domain_end_r);
-           unsigned off= ((b & 0x3f)<<8) | b2;
+           int off= ((b & 0x3f)<<8) | b2;
            if (off >= endpacket - packet)
-               return False;
+               return RCODE_FORMERR;
            domain=packet+off;
            b=*domain++;
-           if (!b) return FORMERR
+           if (!b) return RCODE_FORMERR;
            /* now fall through to code expecting a literal */
        }
        if ((b & 0xc0) != 0x00)
-           return FORMERR;
+           return RCODE_FORMERR;
        if (nlabels>=maxlabels)
-           return NOTAUTH;
+           return FAKERCODE_NOTAUTH;
        totallen+=b+1;
        if (totallen >= MAX_DOMAIN_BYTES) /* we still need a nul label */
-           return FORMERR;
+           return RCODE_FORMERR;
        labels[nlabels].bytes=domain;
        labels[nlabels].len=b;
        nlabels++;
        domain += b;
     }
     if (nlabels <= mydompathlen)
-       return NOTAUTH;
+       return FAKERCODE_NOTAUTH;
     for (i=0; i<mydompathlen; i++) {
        int l=strlen(mydompath[i]);
        const struct labelinpacket *got=&labels[nlabels-mydompathlen];
-       if (got->len != l || memcmp(got->bytes,mydompath[i]))
-           return NOTAUTH;
+       if (got->len != l || memcmp(got->bytes, mydompath[i], l))
+           return FAKERCODE_NOTAUTH;
     }
     /* OK, it's our domain and it has some data and a good
      * number of labels.  Wow. */
-    uint8_t *copyto=&bd->databuf;
+    uint8_t *copyto=bd->databuf;
     for (i=0; i<nlabels-mydompathlen; i++) {
        const uint8_t *p=labels[i].bytes;
        for (j=0; j<labels[i].len; j++) {
            int val=in_table[*p++];
            if (val & 0x80)
-               return NXDOMAIN;
+               return RCODE_NXDOMAIN;
            *copyto++=val;
        }
     }
@@ -154,43 +178,34 @@ int dnsdomaindec_start(struct dnsbitdec *bd, const uint8_t *packet,
     return 0;
 }
 
-static uint8_t in_table[256];
-
-static void dnsdomaindec_globalinit(void) {
-    memset(in_table,0xff,sizeof(in_table));
-    for (i=0; i<32; i++) {
-       in_table[out_table[i]]=i;
-       in_table[toupper((unsigned char)out_table[i])]=i;
-    }
-}
-
-static void inputchar(struct dnsbitdec *bd) {
+static void inputchar(struct dnsdomaindec *bd) {
     /* must be enough input and enough space in pending */
     int ch=*--(bd->in);
     bd->pending <<= 8;
     bd->pending |= ch; /* already decoded */
     bd->npending += 5;
 }
-uint32_t dnsdomaindec_getbits(struct dnsbitdec *bd, int nbits)
+uint32_t dnsdomaindec_getbits(struct dnsdomaindec *bd, int nbits)
 {
     /* must be enough */
     assert(nbits<=28);
-    while (bd->pending < nbits)
-       inputchar();
+    while (bd->npending < nbits)
+       inputchar(bd);
     int newnpending = bd->pending - nbits;
     uint32_t rv = bd->pending >> newnpending;
     bd->pending &= ((uint32_t)1 << newnpending)-1;
     bd->npending = newnpending;
+    return rv;
 }
-uint32_t dnsdomaindec_getu32(struct dnsbitdec *bd)
+uint32_t dnsdomaindec_getu32(struct dnsdomaindec *bd)
 {
     uint32_t lsw=dnsdomaindec_getbits(bd,16);
     uint32_t msw=dnsdomaindec_getbits(bd,16);
     return (msw << 16) | lsw;
 }
-int dnsbitdec_restbytes(struct dnsbitdec *bd, uint8_t outbuf[MAX_DOMAIN_BYTES])
+int dnsdomaindec_restbytes(struct dnsdomaindec *bd, uint8_t outbuf[MAX_DOMAIN_BYTES])
 {
-    uint8_t *out;
+    uint8_t *out = outbuf;
     for (;;) {
        if (bd->npending >= 8) {
            *out++ = bd->pending;
index d2ad5aa5a730717b113eb72073356ee06ffdb7ec..b4b718aeb623f681ca040ce673c4d37533fe0552 100644 (file)
@@ -1,6 +1,33 @@
 
-struct dnsbitenc {
-    /* private for dnsbitenc_... functions; do not access direcctly */
+#ifndef dns_transp_common_h
+#define dns_transp_common_h
+
+#define MAX_DOMAIN_BYTES 255
+
+
+#define RCODE_NOERROR  0
+#define RCODE_FORMERR  1
+#define RCODE_SERVFAIL 2
+#define RCODE_NXDOMAIN 3
+#define RCODE_REFUSED  5
+
+#define FAKERCODE_NOTAUTH -1
+#define FAKERCODE_MYDOMAINTOOLONG -2
+#define FAKERCODE_MYDOMAINLABELTOOLONG -3
+
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+
+
+void dnsdomaindec_globalinit(void);
+
+
+struct dnsdomainenc {
+    /* private for dnsdomainenc_... functions; do not access direcctly */
     uint32_t pending;
     int npending; /* never more than 4 unless we're in the middle */
     uint8_t *out, *bufstop; /* counts backwards */
@@ -15,18 +42,44 @@ struct dnsbitenc {
  *   getresult
  */
 
-void dnsbitenc_start(struct dnsbitenc *be, uint8_t *buf, int buflen);
+int dnsdomainenc_start(struct dnsdomainenc *be, uint8_t *buf, int buflen,
+                      int mydompathlen, const char *const mydompath[]);
+    /* returns -1 if mydompath is too long somehow */
 
-void dnsbitenc_addbits(struct dnsbitenc *be, uint32_t val, int nbits);
+void dnsdomainenc_addbits(struct dnsdomainenc *be, uint32_t val, int nbits);
     /* adds the bottom nbits bits of val; must be enough space; nbits<=28 */
-void dnsbitenc_addu32(struct dnsbitenc *be, uint32_t val);
+void dnsdomainenc_addu32(struct dnsdomainenc *be, uint32_t val);
     /* must be enough space */
 
-int dnsbitenc_restbytes(struct dnsbitenc *be, uint8_t *bytes, int qty);
+int dnsdomainenc_restbytes(struct dnsdomainenc *be,
+                          const uint8_t *bytes, int avail);
     /* returns number of bytes which did not fit */
 
-uint8_t *dnsbitenc_getresult(struct dnsbitenc *be);
+uint8_t *dnsdomainenc_getresult(struct dnsdomainenc *be);
     /* returns pointer into caller-supplied buffer; we have used
      * bytes from the result to the end (so the caller needs to remember
      * the buffer len to know what the encoded length is */
-fixme needs to add mylabels too
+
+
+struct dnsdomaindec {
+    /* private for dnsbitdec_... functions; do not access direcctly */
+    uint8_t databuf[MAX_DOMAIN_BYTES];
+    const uint8_t *in;
+    uint32_t pending;
+    int npending;
+};
+
+int dnsdomaindec_start(struct dnsdomaindec *bd, const uint8_t *packet,
+                      const uint8_t *endpacket, const uint8_t *domain,
+                      int mydompathlen, const char *const mydompath[],
+                      const uint8_t **domain_end_r);
+
+uint32_t dnsdomaindec_getbits(struct dnsdomaindec *bd, int nbits);
+
+uint32_t dnsdomaindec_getu32(struct dnsdomaindec *bd);
+
+int dnsdomaindec_restbytes(struct dnsdomaindec *bd,
+                          uint8_t outbuf[MAX_DOMAIN_BYTES]);
+
+
+#endif /* dns_transp_common_h */