/*
- * $Id: rfc1035.c,v 1.24 2002/03/19 03:03:12 wessels Exp $
+ * $Id: rfc1035.c,v 1.25 2002/03/29 05:49:23 wessels Exp $
*
* Low level DNS protocol routines
* AUTHOR: Duane Wessels
* Returns 0 (success) or 1 (error)
*/
static int
-rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns)
+rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns, int rflag)
{
off_t no = 0;
unsigned char c;
/* blasted compression */
unsigned short s;
off_t ptr;
+ if (rflag) /* pointer loop */
+ return 1;
memcpy(&s, buf + (*off), sizeof(s));
s = ntohs(s);
(*off) += sizeof(s);
/* Make sure the pointer is inside this message */
if (ptr >= sz)
return 1;
- return rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no);
+ return rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no, rflag + 1);
} else if (c > RFC1035_MAXLABELSZ) {
/*
* "(The 10 and 01 combinations are reserved for future use.)"
len = (size_t) c;
if (len == 0)
break;
- if (len > (ns - 1))
- len = ns - 1;
+ if (len > (ns - no - 1)) /* label won't fit */
+ return 1;
if ((*off) + len > sz) /* message is too short */
return 1;
memcpy(name + no, buf + (*off), len);
no += len;
*(name + (no++)) = '.';
}
- } while (c > 0);
+ } while (c > 0 && no < ns);
*(name + no - 1) = '\0';
/* make sure we didn't allow someone to overflow the name buffer */
assert(no <= ns);
unsigned short s;
unsigned int i;
off_t rdata_off;
- if (rfc1035NameUnpack(buf, sz, off, RR->name, RFC1035_MAXHOSTNAMESZ)) {
+ if (rfc1035NameUnpack(buf, sz, off, RR->name, RFC1035_MAXHOSTNAMESZ, 0)) {
RFC1035_UNPACK_DEBUG;
memset(RR, '\0', sizeof(*RR));
return 1;
case RFC1035_TYPE_PTR:
RR->rdata = malloc(RFC1035_MAXHOSTNAMESZ);
rdata_off = *off;
- if (rfc1035NameUnpack(buf, sz, &rdata_off, RR->rdata, RFC1035_MAXHOSTNAMESZ))
+ if (rfc1035NameUnpack(buf, sz, &rdata_off, RR->rdata, RFC1035_MAXHOSTNAMESZ, 0))
return 1;
if (rdata_off != ((*off) + RR->rdlength)) {
/*