diff options
Diffstat (limited to 'src/dnsstub/dns_packet.c')
-rw-r--r-- | src/dnsstub/dns_packet.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/dnsstub/dns_packet.c b/src/dnsstub/dns_packet.c new file mode 100644 index 0000000..b131635 --- /dev/null +++ b/src/dnsstub/dns_packet.c @@ -0,0 +1,85 @@ +#include "error.h" +#include "dnsresolv.h" + +/** + * @file dns_packet.c + * @author djb + * @ref ucspi-tcp + * @brief DNS low level packet routine + * @brief DNS should have used LZ77 instead of its own sophomoric compression algorithm. + */ + +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 = EPROTO; 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 = EPROTO; + 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 = EPROTO; + return 0; +} |