/* dns stringing functions */
#include <errno.h>
#include "ldapdns.h"
#include "mem.h"
void name_to_dns_fix(str_t retbuf, char *name, int splithow)
{
register int ch;
ch = (splithow ? '|' : '.');
if (splithow == 2) ch = '@';
/* safe if name is truly ASCIIZ */
while (*name == ch)
++name;
str_init(retbuf);
while (*name) {
register char *start = name;
register unsigned length;
register int tmp;
while (*name && *name != ch)
++name;
length = name - start;
if (length >= 127 && !splithow) {
warning("name-segment too long: %s", name);
return; /* invalid */
}
while (length) {
/* tmp is a function of length, and length must be >0 */
str_addch(retbuf, tmp = length > 127 ? 127 : length);
str_catb(retbuf, start, tmp);
length -= tmp;
start += tmp;
}
while (*name == ch)
++name;
if (splithow == 2) {
splithow = 0;
ch = '.';
}
}
}
void dns_to_name(str_t retbuf, char *dns, int joinhow)
{
const char *ch = ".|@";
str_init(retbuf);
while (*dns) {
str_catb(retbuf, dns+1, dns[0]);
str_addch(retbuf, ch[joinhow]);
if (joinhow == 2) joinhow = 0;
dns += (dns[0]+1);
}
/* will have two dots... */
str_chop(retbuf);
}
/* these lists are built BACKWARDS so that we can just pop() off the first
* entries easily when searching for wildcards
*/
void join_name_parts(str_t retbuf, list_t p)
{
str_init(retbuf);
while (p) {
str_cat(retbuf, p->str);
str_addch(retbuf, '.');
p = p->next;
}
str_chop(retbuf);
}
void join_dns_parts(str_t retbuf, list_t p)
{
str_init(retbuf);
while (p) {
str_addch(retbuf, __str_clen(p->str));
str_cat(retbuf, p->str);
p = p->next;
}
str_chop(retbuf);
}
list_t split_name_parts(char *name)
{
/* name is modified by this routine! */
list_t p = 0;
register char *start = name;
while (*start == '.') start++;
while (*start) {
while (*start && *start != '.') start++;
if (*start) {
*start = 0;
start++;
while (*start == '.') start++;
}
list_push(&p, name);
name = start;
}
/* list is in reverse */
list_reverse(&p);
return p;
}
list_t split_dns_parts(char *name)
{
/* name is modified by this routine! */
list_t p = 0;
register unsigned int length, nl;
while (*name) {
length = *name;
if (length == 0)
break;
nl = name[length+1];
name[length+1] = 0;
list_push(&p, name+1);
name += length;
}
/* list is in reverse */
list_reverse(&p);
return p;
}
/* packet related */
unsigned int dns_packet_copy(dns_ctx *c, char *out,unsigned int outlen)
{
while (outlen) {
if (c->request_pos >= c->request_len) {
errno = EBADMSG;
return 0;
}
*out = c->request_buf[c->request_pos++];
++out; --outlen;
}
return c->request_pos;
}
unsigned int dns_packet_skipname(dns_ctx *c)
{
unsigned char ch;
for (;;) { /* should be safe because it is bounded and breaks on non-movement */
if (c->request_pos >= c->request_len)
break;
ch = c->request_buf[c->request_pos++];
if (ch >= 192) { c->request_pos++; return c->request_pos; }
if (ch >= 64) break;
if (!ch) return c->request_pos;
c->request_pos += ch;
}
errno = EBADMSG;
return 0;
}
unsigned int dns_packet_getname(dns_ctx *c, 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 (;;) { /* should be safe: breaks on non-movement;
OR after 1000 iterations */
if (c->request_pos >= c->request_len) goto PROTO;
ch = c->request_buf[c->request_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 (c->request_pos >= c->request_len)
goto PROTO;
ch = c->request_buf[c->request_pos++];
if (!firstcompress)
firstcompress = c->request_pos;
c->request_pos = where + ch;
if (c->request_pos >= c->request_len)
goto PROTO;
ch = c->request_buf[c->request_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) c->request_pos = firstcompress;
return c->request_pos;
PROTO:
errno = EBADMSG;
return 0;
}
unsigned int dns_domain_length(const char *dn)
{
const char *x;
unsigned char c;
x = dn;
while ((c = *x++)) /* should be safe if dn is a valid dns-encoded */
x += (unsigned int) c;
return x - dn;
}
void dns_domain_lower(char *dn)
{
char *x;
int i;
x = dn;
while (*x) { /* should be safe if dn is a valid dns-encoded */
for (i = 1; i <= *x; i++) {
/* Clib */
dn[i] = tolower(dn[i]);
}
dn += *x;
dn++;
x = dn;
}
}
int dns_domain_copy(char **out, char *in)
{
bin_t retval;
unsigned int len;
len = dns_domain_length(in);
bin_init(retval);
bin_copy(retval, in, len);
if (*out) mem_free(*out);
*out = caddr(retval);
return 1;
}
syntax highlighted by Code2HTML, v. 0.9.1