You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
78 lines
1.7 KiB
C
78 lines
1.7 KiB
C
/*
|
|
DNS should have used LZ77 instead of its own sophomoric compression algorithm.
|
|
*/
|
|
|
|
#include <errno.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 = EINVAL; 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 = EINVAL;
|
|
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 = EINVAL;
|
|
return 0;
|
|
}
|