mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-21 23:31:06 -05:00
copy and decompress.
git-svn-id: file:///svn/unbound/trunk@242 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
4283fec985
commit
ae30307d6d
3 changed files with 162 additions and 33 deletions
|
|
@ -1,3 +1,6 @@
|
||||||
|
17 April 2007: Wouter
|
||||||
|
- copy and decompress dnames.
|
||||||
|
|
||||||
16 April 2007: Wouter
|
16 April 2007: Wouter
|
||||||
- following a small change in LDNS, parsing code calculates the
|
- following a small change in LDNS, parsing code calculates the
|
||||||
memory size to allocate for rrs.
|
memory size to allocate for rrs.
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,8 @@ struct rr_parse;
|
||||||
|
|
||||||
/** number of buckets in parse rrset hash table. Must be power of 2. */
|
/** number of buckets in parse rrset hash table. Must be power of 2. */
|
||||||
#define PARSE_TABLE_SIZE 1024
|
#define PARSE_TABLE_SIZE 1024
|
||||||
|
/** Maximum TTL that is allowed. */
|
||||||
|
#define MAX_TTL 3600*24*365*10 /* ten years */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data stored in scratch pad memory during parsing.
|
* Data stored in scratch pad memory during parsing.
|
||||||
|
|
@ -593,6 +595,46 @@ parse_alloc_rrset_keys(struct msg_parse* msg, struct reply_info* rep,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain size in the packet of an rr type, that is before dname type.
|
||||||
|
* Do TYPE_DNAME, and type STR, yourself.
|
||||||
|
* @param rdf: the rdf type from the descriptor.
|
||||||
|
* @return: size in octets. 0 on failure.
|
||||||
|
*/
|
||||||
|
static size_t
|
||||||
|
get_rdf_size(ldns_rdf_type rdf)
|
||||||
|
{
|
||||||
|
switch(rdf) {
|
||||||
|
case LDNS_RDF_TYPE_CLASS:
|
||||||
|
case LDNS_RDF_TYPE_ALG:
|
||||||
|
case LDNS_RDF_TYPE_INT8:
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case LDNS_RDF_TYPE_INT16:
|
||||||
|
case LDNS_RDF_TYPE_TYPE:
|
||||||
|
case LDNS_RDF_TYPE_CERT_ALG:
|
||||||
|
return 2;
|
||||||
|
break;
|
||||||
|
case LDNS_RDF_TYPE_INT32:
|
||||||
|
case LDNS_RDF_TYPE_TIME:
|
||||||
|
case LDNS_RDF_TYPE_A:
|
||||||
|
case LDNS_RDF_TYPE_PERIOD:
|
||||||
|
return 4;
|
||||||
|
break;
|
||||||
|
case LDNS_RDF_TYPE_TSIGTIME:
|
||||||
|
return 6;
|
||||||
|
break;
|
||||||
|
case LDNS_RDF_TYPE_AAAA:
|
||||||
|
return 16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log_assert(false); /* add type above */
|
||||||
|
/* only types that appear before a domain *
|
||||||
|
* name are needed. rest is simply copied. */
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** calculate the size of one rr */
|
/** calculate the size of one rr */
|
||||||
static int
|
static int
|
||||||
calc_size(ldns_buffer* pkt, uint16_t type, struct rr_parse* rr)
|
calc_size(ldns_buffer* pkt, uint16_t type, struct rr_parse* rr)
|
||||||
|
|
@ -610,51 +652,36 @@ calc_size(ldns_buffer* pkt, uint16_t type, struct rr_parse* rr)
|
||||||
int count = (int)desc->_dname_count;
|
int count = (int)desc->_dname_count;
|
||||||
int rdf = 0;
|
int rdf = 0;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
size_t oldpos;
|
||||||
/* skip first part. */
|
/* skip first part. */
|
||||||
while(count) {
|
while(count) {
|
||||||
switch(desc->_wireformat[rdf]) {
|
switch(desc->_wireformat[rdf]) {
|
||||||
case LDNS_RDF_TYPE_DNAME:
|
case LDNS_RDF_TYPE_DNAME:
|
||||||
/* decompress every domain name */
|
/* decompress every domain name */
|
||||||
|
oldpos = ldns_buffer_position(pkt);
|
||||||
if((len = pkt_dname_len(pkt)) == 0)
|
if((len = pkt_dname_len(pkt)) == 0)
|
||||||
return 0;
|
return 0; /* malformed dname */
|
||||||
|
if(ldns_buffer_position(pkt)-oldpos > pkt_len)
|
||||||
|
return 0; /* dname exceeds rdata */
|
||||||
|
pkt_len -= ldns_buffer_position(pkt)-oldpos;
|
||||||
rr->size += len;
|
rr->size += len;
|
||||||
count--;
|
count--;
|
||||||
|
len = 0;
|
||||||
break;
|
break;
|
||||||
case LDNS_RDF_TYPE_STR:
|
case LDNS_RDF_TYPE_STR:
|
||||||
|
if(pkt_len < 1)
|
||||||
|
return 0; /* len byte exceeds rdata */
|
||||||
len = ldns_buffer_current(pkt)[0] + 1;
|
len = ldns_buffer_current(pkt)[0] + 1;
|
||||||
rr->size += len;
|
|
||||||
ldns_buffer_skip(pkt, (ssize_t)len);
|
|
||||||
break;
|
break;
|
||||||
case LDNS_RDF_TYPE_CLASS:
|
|
||||||
case LDNS_RDF_TYPE_ALG:
|
|
||||||
case LDNS_RDF_TYPE_INT8:
|
|
||||||
ldns_buffer_skip(pkt, 1);
|
|
||||||
rr->size += 1;
|
|
||||||
break;
|
|
||||||
case LDNS_RDF_TYPE_INT16:
|
|
||||||
case LDNS_RDF_TYPE_TYPE:
|
|
||||||
case LDNS_RDF_TYPE_CERT_ALG:
|
|
||||||
ldns_buffer_skip(pkt, 2);
|
|
||||||
rr->size += 2;
|
|
||||||
break;
|
|
||||||
case LDNS_RDF_TYPE_INT32:
|
|
||||||
case LDNS_RDF_TYPE_TIME:
|
|
||||||
case LDNS_RDF_TYPE_A:
|
|
||||||
case LDNS_RDF_TYPE_PERIOD:
|
|
||||||
ldns_buffer_skip(pkt, 4);
|
|
||||||
rr->size += 4;
|
|
||||||
break;
|
|
||||||
case LDNS_RDF_TYPE_TSIGTIME:
|
|
||||||
ldns_buffer_skip(pkt, 6);
|
|
||||||
rr->size += 6;
|
|
||||||
break;
|
|
||||||
case LDNS_RDF_TYPE_AAAA:
|
|
||||||
ldns_buffer_skip(pkt, 16);
|
|
||||||
rr->size += 16;
|
|
||||||
default:
|
default:
|
||||||
log_assert(false); /* add type above */
|
len = get_rdf_size(desc->_wireformat[rdf]);
|
||||||
/* only types that appear before a domain *
|
}
|
||||||
* name are needed. rest is simply copied. */
|
if(len) {
|
||||||
|
if(pkt_len < len)
|
||||||
|
return 0; /* exceeds rdata */
|
||||||
|
pkt_len -= len;
|
||||||
|
ldns_buffer_skip(pkt, (ssize_t)len);
|
||||||
|
rr->size += len;
|
||||||
}
|
}
|
||||||
rdf++;
|
rdf++;
|
||||||
}
|
}
|
||||||
|
|
@ -670,12 +697,109 @@ parse_rr_size(ldns_buffer* pkt, struct rrset_parse* pset, size_t* allocsize)
|
||||||
{
|
{
|
||||||
struct rr_parse* p = pset->rr_first;
|
struct rr_parse* p = pset->rr_first;
|
||||||
*allocsize = 0;
|
*allocsize = 0;
|
||||||
|
/* size of rrs */
|
||||||
while(p) {
|
while(p) {
|
||||||
if(!calc_size(pkt, ntohs(pset->type), p))
|
if(!calc_size(pkt, ntohs(pset->type), p))
|
||||||
return 0;
|
return 0;
|
||||||
*allocsize += p->size;
|
*allocsize += p->size;
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
}
|
||||||
|
/* TODO calc size of rrsig */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** do the rdata copy */
|
||||||
|
static int
|
||||||
|
rdata_copy(ldns_buffer* pkt, struct rrset_parse* pset,
|
||||||
|
struct packed_rrset_data* data, uint8_t* to, struct rr_parse* rr)
|
||||||
|
{
|
||||||
|
uint16_t pkt_len;
|
||||||
|
uint32_t ttl;
|
||||||
|
const ldns_rr_descriptor* desc;
|
||||||
|
ldns_buffer_set_position(pkt, (size_t)
|
||||||
|
(rr->ttl_data - ldns_buffer_begin(pkt)));
|
||||||
|
if(ldns_buffer_remaining(pkt) < 6)
|
||||||
|
return 0;
|
||||||
|
ttl = ldns_buffer_read_u32(pkt);
|
||||||
|
if(ttl < data->ttl)
|
||||||
|
data->ttl = ttl;
|
||||||
|
/* insert decompressed size into memory rdata len */
|
||||||
|
pkt_len = htons(rr->size);
|
||||||
|
memmove(to, &pkt_len, sizeof(uint16_t));
|
||||||
|
to += 2;
|
||||||
|
/* read packet rdata len */
|
||||||
|
pkt_len = ldns_buffer_read_u16(pkt);
|
||||||
|
if(ldns_buffer_remaining(pkt) < pkt_len)
|
||||||
|
return 0;
|
||||||
|
log_assert((size_t)pkt_len+2 <= rr->size);
|
||||||
|
desc = ldns_rr_descript(ntohs(pset->type));
|
||||||
|
if(desc->_dname_count > 0) {
|
||||||
|
int count = (int)desc->_dname_count;
|
||||||
|
int rdf = 0;
|
||||||
|
size_t len;
|
||||||
|
size_t oldpos;
|
||||||
|
/* decompress dnames. */
|
||||||
|
while(count) {
|
||||||
|
switch(desc->_wireformat[rdf]) {
|
||||||
|
case LDNS_RDF_TYPE_DNAME:
|
||||||
|
oldpos = ldns_buffer_position(pkt);
|
||||||
|
dname_pkt_copy(pkt, to,
|
||||||
|
ldns_buffer_current(pkt));
|
||||||
|
to += pkt_dname_len(pkt);
|
||||||
|
pkt_len -= ldns_buffer_position(pkt)-oldpos;
|
||||||
|
count--;
|
||||||
|
len = 0;
|
||||||
|
break;
|
||||||
|
case LDNS_RDF_TYPE_STR:
|
||||||
|
len = ldns_buffer_current(pkt)[0] + 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
len = get_rdf_size(desc->_wireformat[rdf]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(len) {
|
||||||
|
memmove(to, ldns_buffer_current(pkt), len);
|
||||||
|
to += len;
|
||||||
|
ldns_buffer_skip(pkt, (ssize_t)len);
|
||||||
|
log_assert(len <= pkt_len);
|
||||||
|
pkt_len -= len;
|
||||||
|
}
|
||||||
|
rdf++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* copy remaining rdata */
|
||||||
|
if(pkt_len > 0)
|
||||||
|
memmove(to, ldns_buffer_current(pkt), pkt_len);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** copy over the data into packed rrset */
|
||||||
|
static int
|
||||||
|
parse_rr_copy(ldns_buffer* pkt, struct rrset_parse* pset,
|
||||||
|
struct packed_rrset_data* data)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
struct rr_parse* rr = pset->rr_first;
|
||||||
|
uint8_t* nextrdata;
|
||||||
|
data->ttl = MAX_TTL;
|
||||||
|
data->count = pset->rr_count;
|
||||||
|
/* layout: struct - rr_len - rr_data - rdata - rrsig */
|
||||||
|
data->rr_len = (size_t*)((uint8_t*)&data +
|
||||||
|
sizeof(struct packed_rrset_data));
|
||||||
|
data->rr_data = (uint8_t**)(&data->rr_len[data->count]);
|
||||||
|
nextrdata = (uint8_t*)(&data->rr_data[data->count]);
|
||||||
|
data->rrsig_data = 0;
|
||||||
|
data->rrsig_len = 0;
|
||||||
|
for(i=0; i<data->count; i++) {
|
||||||
|
data->rr_len[i] = rr->size;
|
||||||
|
data->rr_data[i] = nextrdata;
|
||||||
|
nextrdata += rr->size;
|
||||||
|
if(!rdata_copy(pkt, pset, data, data->rr_data[i], rr))
|
||||||
|
return 0;
|
||||||
|
rr = rr->next;
|
||||||
|
}
|
||||||
|
/* if rrsig, its rdata is at nextrdata */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -693,6 +817,9 @@ parse_create_rrset(ldns_buffer* pkt, struct rrset_parse* pset,
|
||||||
(sizeof(size_t)+sizeof(uint8_t*)+sizeof(uint32_t)) + allocsize);
|
(sizeof(size_t)+sizeof(uint8_t*)+sizeof(uint32_t)) + allocsize);
|
||||||
if(!*data)
|
if(!*data)
|
||||||
return LDNS_RCODE_SERVFAIL;
|
return LDNS_RCODE_SERVFAIL;
|
||||||
|
/* copy & decompress */
|
||||||
|
if(!parse_rr_copy(pkt, pset, *data))
|
||||||
|
return LDNS_RCODE_SERVFAIL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,6 @@ struct ub_packed_rrset_key {
|
||||||
* o base struct
|
* o base struct
|
||||||
* o rr_len size_t array
|
* o rr_len size_t array
|
||||||
* o rr_data uint8_t* array
|
* o rr_data uint8_t* array
|
||||||
* o rr_ttl uint32_t array
|
|
||||||
* o rr_data rdata wireformats
|
* o rr_data rdata wireformats
|
||||||
* o rrsig_data rdata wireformat
|
* o rrsig_data rdata wireformat
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue