dname's as decompressed bindata's

This commit is contained in:
Willem Toorop 2015-02-17 21:28:39 +01:00
parent 3c5b28ffaf
commit 73776bcd48
3 changed files with 124 additions and 17 deletions

View File

@ -113,6 +113,96 @@ priv_getdns_rr_iter_next(priv_getdns_rr_iter *i)
return find_rrtype(i);
}
static uint8_t *
dname_if_or_as_decompressed(uint8_t *pkt, uint8_t *pkt_end, uint8_t *pos,
uint8_t *buf, size_t *len, size_t refs)
{
uint16_t offset;
uint8_t *start, *dst;
assert(pkt);
assert(pkt_end);
assert(pos);
assert(buf);
assert(len);
if (refs > 256)
goto error;
if ((*pos & 0xC0) == 0xC0) {
if (pos + 1 >= pkt_end)
goto error;
offset = gldns_read_uint16(pos) & 0x3FFF;
if (pkt + offset >= pkt_end)
goto error;
return dname_if_or_as_decompressed(pkt, pkt_end, pkt + offset,
buf, len, refs + 1);
}
if (*pos & 0xC0)
goto error;
start = pos;
*len = 0;
while (*pos) {
if ((*pos & 0xC0) == 0xC0)
break;
else if (*pos & 0xC0)
goto error;
*len += *pos + 1;
pos += *pos + 1;
}
if (!*pos) {
*len += 1;
return start;
}
dst = buf;
for (;;) {
if (pos > start) {
if (dst + (pos - start) > buf + 255)
goto error;
(void) memcpy(dst, start, pos - start);
dst += (pos - start);
start = pos;
}
if ((*pos & 0xC0) == 0xC0) {
if (pos + 1 >= pkt_end)
goto error;
offset = gldns_read_uint16(pos) & 0x3FFF;
if (pkt + offset >= pkt_end)
goto error;
start = pos = pkt + offset;
if (++refs > 256)
goto error;
}
if ((*pos & 0xC0) == 0xC0)
continue;
else if (*pos & 0xC0)
goto error;
else if (!*pos) {
*len += 1;
*dst = 0;
return buf;
}
*len += *pos + 1;
pos += *pos + 1;
}
error:
*len = 0;
return NULL;
}
uint8_t *
priv_getdns_owner_if_or_as_decompressed(priv_getdns_rr_iter *i,
uint8_t *ff_bytes, size_t *len)
{
return dname_if_or_as_decompressed(i->pkt, i->pkt_end, i->pos,
ff_bytes, len, 0);
}
static priv_getdns_rdf_iter *
rdf_iter_find_nxt(priv_getdns_rdf_iter *i)
@ -215,3 +305,11 @@ done:
return NULL;
}
uint8_t *
priv_getdns_rdf_if_or_as_decompressed(
priv_getdns_rdf_iter *i, uint8_t *ff_bytes, size_t *len)
{
return dname_if_or_as_decompressed(i->pkt, i->pkt_end, i->pos,
ff_bytes, len, 0);
}

View File

@ -64,6 +64,9 @@ priv_getdns_rr_iter *priv_getdns_rr_iter_init(priv_getdns_rr_iter *i,
priv_getdns_rr_iter *priv_getdns_rr_iter_next(priv_getdns_rr_iter *i);
uint8_t *priv_getdns_owner_if_or_as_decompressed(
priv_getdns_rr_iter *i, uint8_t *ff_bytes, size_t *len);
static inline gldns_pkt_section
priv_getdns_rr_iter_section(priv_getdns_rr_iter *i)
{
@ -96,5 +99,7 @@ priv_getdns_rdf_iter *priv_getdns_rdf_iter_init(priv_getdns_rdf_iter *i,
priv_getdns_rdf_iter *priv_getdns_rdf_iter_next(priv_getdns_rdf_iter *i);
uint8_t *priv_getdns_rdf_if_or_as_decompressed(
priv_getdns_rdf_iter *i, uint8_t *ff_bytes, size_t *len);
#endif

View File

@ -321,14 +321,15 @@ priv_getdns_rr_iter2rr_dict(getdns_context *context, priv_getdns_rr_iter *i)
priv_getdns_rdf_iter rdf_storage, *rdf;
getdns_list *repeat_list = NULL;
getdns_dict *repeat_dict = NULL;
uint8_t ff_bytes[256];
assert(context);
assert(i);
if (!(rr_dict = getdns_dict_create_with_context(context)))
return NULL;
bindata.size = i->rr_type - i->pos;
bindata.data = i->pos;
bindata.data = priv_getdns_owner_if_or_as_decompressed(
i, ff_bytes, &bindata.size);
/* question */
if (priv_getdns_rr_iter_section(i) == GLDNS_SECTION_QUESTION) {
@ -371,24 +372,25 @@ priv_getdns_rr_iter2rr_dict(getdns_context *context, priv_getdns_rr_iter *i)
if (rdf->rdd_pos->type & GETDNS_RDF_INTEGER) {
val_type = t_int;
switch (rdf->rdd_pos->type & GETDNS_RDF_FIXEDSZ) {
case 1: if (getdns_dict_set_int(rdata_dict,
rdf->rdd_pos->name, (uint32_t)*rdf->pos))
goto rdata_error;
case 1: int_val = *rdf->pos;
break;
case 2: if (getdns_dict_set_int(rdata_dict,
rdf->rdd_pos->name, (uint32_t)
gldns_read_uint16(rdf->pos)))
goto rdata_error;
case 2: int_val = gldns_read_uint16(rdf->pos);
break;
case 4: if (getdns_dict_set_int(rdata_dict,
rdf->rdd_pos->name, (uint32_t)
gldns_read_uint32(rdf->pos)))
goto rdata_error;
case 4: int_val = gldns_read_uint32(rdf->pos);
break;
default:
break;
goto rdata_error;
}
/* TODO: if (rdf->rdd_pos->type & GETDNS_RDF_DNAME) { */
} else if ((rdf->rdd_pos->type & GETDNS_RDF_DNAME) ==
GETDNS_RDF_DNAME) {
val_type = t_bindata;
fprintf(stderr, "dname (%s - %d)\n",
rdf->rdd_pos->name, (int)(rdf->nxt - rdf->pos));
bindata.data = priv_getdns_rdf_if_or_as_decompressed(
rdf, ff_bytes, &bindata.size);
} else if (rdf->rdd_pos->type & GETDNS_RDF_BINDATA) {
val_type = t_bindata;
if (rdf->rdd_pos->type & GETDNS_RDF_FIXEDSZ) {
@ -404,11 +406,13 @@ priv_getdns_rr_iter2rr_dict(getdns_context *context, priv_getdns_rr_iter *i)
case 0x200:
bindata.size = gldns_read_uint16(rdf->pos);
bindata.data = rdf->pos + 2;
break;
break;
default:
fprintf(stderr, "REMAINING (%s - %d)\n",
rdf->rdd_pos->name, (int)(rdf->nxt - rdf->pos));
bindata.size = rdf->nxt - rdf->pos;
bindata.data = rdf->pos;
break;
break;
}
} else
assert(0);