/*
- * $Id: rfc1035.c,v 1.34 2005/01/23 14:55:45 serassio Exp $
+ * $Id: rfc1035.c,v 1.35 2005/01/23 14:59:06 serassio 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, int rdepth)
+rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, unsigned short *rdlength, char *name, size_t ns, int rdepth)
{
off_t no = 0;
unsigned char c;
/* Make sure the pointer is inside this message */
if (ptr >= sz)
return 1;
- return rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no, rdepth + 1);
+ return rfc1035NameUnpack(buf, sz, &ptr, rdlength, name + no, ns - no, rdepth + 1);
} else if (c > RFC1035_MAXLABELSZ) {
/*
* "(The 10 and 01 combinations are reserved for future use.)"
(*off) += len;
no += len;
*(name + (no++)) = '.';
+ if (rdlength)
+ *rdlength += len + 1;
}
} while (c > 0 && no < ns);
if (no)
{
unsigned short s;
unsigned int i;
+ unsigned short rdlength;
off_t rdata_off;
- if (rfc1035NameUnpack(buf, sz, off, RR->name, RFC1035_MAXHOSTNAMESZ, 0)) {
+ if (rfc1035NameUnpack(buf, sz, off, NULL, RR->name, RFC1035_MAXHOSTNAMESZ, 0)) {
RFC1035_UNPACK_DEBUG;
memset(RR, '\0', sizeof(*RR));
return 1;
RR->ttl = ntohl(i);
memcpy(&s, buf + (*off), sizeof(s));
(*off) += sizeof(s);
- if ((*off) + ntohs(s) > sz) {
+ rdlength = ntohs(s);
+ if ((*off) + rdlength > sz) {
/*
* We got a truncated packet. 'dnscache' truncates UDP
* replies at 512 octets, as per RFC 1035.
memset(RR, '\0', sizeof(*RR));
return 1;
}
- RR->rdlength = ntohs(s);
+ RR->rdlength = rdlength;
switch (RR->type) {
case RFC1035_TYPE_PTR:
RR->rdata = malloc(RFC1035_MAXHOSTNAMESZ);
rdata_off = *off;
- if (rfc1035NameUnpack(buf, sz, &rdata_off, RR->rdata, RFC1035_MAXHOSTNAMESZ, 0))
+ RR->rdlength = 0; /* Filled in by rfc1035NameUnpack */
+ if (rfc1035NameUnpack(buf, sz, &rdata_off, &RR->rdlength, RR->rdata, RFC1035_MAXHOSTNAMESZ, 0))
return 1;
- if (rdata_off != ((*off) + RR->rdlength)) {
+ if (rdata_off != ((*off) + rdlength)) {
/*
* This probably doesn't happen for valid packets, but
* I want to make sure that NameUnpack doesn't go beyond
* the RDATA area.
*/
RFC1035_UNPACK_DEBUG;
+ free(RR->rdata);
memset(RR, '\0', sizeof(*RR));
return 1;
}
break;
case RFC1035_TYPE_A:
default:
- RR->rdata = malloc(RR->rdlength);
- memcpy(RR->rdata, buf + (*off), RR->rdlength);
+ RR->rdata = malloc(rdlength);
+ memcpy(RR->rdata, buf + (*off), rdlength);
break;
}
- (*off) += RR->rdlength;
+ (*off) += rdlength;
assert((*off) <= sz);
return 0;
}