diff options
author | Henryk Plötz <henryk@ploetzli.ch> | 2014-10-03 19:58:52 +0200 |
---|---|---|
committer | Henryk Plötz <henryk@ploetzli.ch> | 2014-10-03 19:58:52 +0200 |
commit | 0e5b2871ca6456b01d4bf037a6e68badf1ff1a41 (patch) | |
tree | 97b95b74c9618d85da9aa9451a55a819cd7b1c2e /dns_packet.c | |
download | tinydnssec-0e5b2871ca6456b01d4bf037a6e68badf1ff1a41.tar.gz tinydnssec-0e5b2871ca6456b01d4bf037a6e68badf1ff1a41.tar.bz2 |
Initial commit of djbdns-1.05.tar.gz
Source was http://cr.yp.to/djbdns/djbdns-1.05.tar.gz, SHA1 2efdb3a039d0c548f40936aa9cb30829e0ce8c3d
Diffstat (limited to 'dns_packet.c')
-rw-r--r-- | dns_packet.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/dns_packet.c b/dns_packet.c new file mode 100644 index 0000000..6d66eeb --- /dev/null +++ b/dns_packet.c @@ -0,0 +1,77 @@ +/* +DNS should have used LZ77 instead of its own sophomoric compression algorithm. +*/ + +#include "error.h" +#include "dns.h" + +unsigned int dns_packet_copy(const char *buf,unsigned int len,unsigned int pos,char *out,unsigned int outlen) +{ + while (outlen) { + if (pos >= len) { errno = error_proto; return 0; } + *out = buf[pos++]; + ++out; --outlen; + } + return pos; +} + +unsigned int dns_packet_skipname(const char *buf,unsigned int len,unsigned int pos) +{ + unsigned char ch; + + for (;;) { + if (pos >= len) break; + ch = buf[pos++]; + if (ch >= 192) return pos + 1; + if (ch >= 64) break; + if (!ch) return pos; + pos += ch; + } + + errno = error_proto; + return 0; +} + +unsigned int dns_packet_getname(const char *buf,unsigned int len,unsigned int pos,char **d) +{ + unsigned int loop = 0; + unsigned int state = 0; + unsigned int firstcompress = 0; + unsigned int where; + unsigned char ch; + char name[255]; + unsigned int namelen = 0; + + for (;;) { + if (pos >= len) goto PROTO; ch = buf[pos++]; + if (++loop >= 1000) goto PROTO; + + if (state) { + if (namelen + 1 > sizeof name) goto PROTO; name[namelen++] = ch; + --state; + } + else { + while (ch >= 192) { + where = ch; where -= 192; where <<= 8; + if (pos >= len) goto PROTO; ch = buf[pos++]; + if (!firstcompress) firstcompress = pos; + pos = where + ch; + if (pos >= len) goto PROTO; ch = buf[pos++]; + if (++loop >= 1000) goto PROTO; + } + if (ch >= 64) goto PROTO; + if (namelen + 1 > sizeof name) goto PROTO; name[namelen++] = ch; + if (!ch) break; + state = ch; + } + } + + if (!dns_domain_copy(d,name)) return 0; + + if (firstcompress) return firstcompress; + return pos; + + PROTO: + errno = error_proto; + return 0; +} |