From 4722e11ffec50306bf7ded7e93ba6c8f371c55f5 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 1 Aug 2011 12:33:09 +0100 Subject: [PATCH] WIP DNS bitenc test compiles --- Makefile.in | 3 ++ dns-bitenc-test.c | 67 +++++++++++++++--------- dns-transp-common.c | 125 +++++++++++++++++++++++++------------------- dns-transp-common.h | 69 +++++++++++++++++++++--- 4 files changed, 176 insertions(+), 88 deletions(-) diff --git a/Makefile.in b/Makefile.in index e82baf6..0d1ff1a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 diff --git a/dns-bitenc-test.c b/dns-bitenc-test.c index 5d09cfb..a11ecd9 100644 --- a/dns-bitenc-test.c +++ b/dns-bitenc-test.c @@ -1,37 +1,50 @@ +/* + * Simple test program + */ + +#include "dns-transp-common.h" + +#include +#include + #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(); + } + } +} diff --git a/dns-transp-common.c b/dns-transp-common.c index 2505828..1b8eb86 100644 --- a/dns-transp-common.c +++ b/dns-transp-common.c @@ -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; ilen != 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; iin); 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; diff --git a/dns-transp-common.h b/dns-transp-common.h index d2ad5aa..b4b718a 100644 --- a/dns-transp-common.h +++ b/dns-transp-common.h @@ -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 +#include +#include +#include +#include + + +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 */ -- 2.30.2