copy and decompress.
git-svn-id: https://unbound.nlnetlabs.nl/svn/trunk@242 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
6f8a76a4fd
commit
d63a6bdd6f
@ -1,3 +1,6 @@
|
||||
17 April 2007: Wouter
|
||||
- copy and decompress dnames.
|
||||
|
||||
16 April 2007: Wouter
|
||||
- following a small change in LDNS, parsing code calculates the
|
||||
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. */
|
||||
#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.
|
||||
@ -593,6 +595,46 @@ parse_alloc_rrset_keys(struct msg_parse* msg, struct reply_info* rep,
|
||||
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 */
|
||||
static int
|
||||
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 rdf = 0;
|
||||
size_t len;
|
||||
size_t oldpos;
|
||||
/* skip first part. */
|
||||
while(count) {
|
||||
switch(desc->_wireformat[rdf]) {
|
||||
case LDNS_RDF_TYPE_DNAME:
|
||||
/* decompress every domain name */
|
||||
oldpos = ldns_buffer_position(pkt);
|
||||
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;
|
||||
count--;
|
||||
len = 0;
|
||||
break;
|
||||
case LDNS_RDF_TYPE_STR:
|
||||
if(pkt_len < 1)
|
||||
return 0; /* len byte exceeds rdata */
|
||||
len = ldns_buffer_current(pkt)[0] + 1;
|
||||
rr->size += len;
|
||||
ldns_buffer_skip(pkt, (ssize_t)len);
|
||||
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:
|
||||
log_assert(false); /* add type above */
|
||||
/* only types that appear before a domain *
|
||||
* name are needed. rest is simply copied. */
|
||||
len = get_rdf_size(desc->_wireformat[rdf]);
|
||||
}
|
||||
if(len) {
|
||||
if(pkt_len < len)
|
||||
return 0; /* exceeds rdata */
|
||||
pkt_len -= len;
|
||||
ldns_buffer_skip(pkt, (ssize_t)len);
|
||||
rr->size += len;
|
||||
}
|
||||
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;
|
||||
*allocsize = 0;
|
||||
/* size of rrs */
|
||||
while(p) {
|
||||
if(!calc_size(pkt, ntohs(pset->type), p))
|
||||
return 0;
|
||||
*allocsize += p->size;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -693,6 +817,9 @@ parse_create_rrset(ldns_buffer* pkt, struct rrset_parse* pset,
|
||||
(sizeof(size_t)+sizeof(uint8_t*)+sizeof(uint32_t)) + allocsize);
|
||||
if(!*data)
|
||||
return LDNS_RCODE_SERVFAIL;
|
||||
/* copy & decompress */
|
||||
if(!parse_rr_copy(pkt, pset, *data))
|
||||
return LDNS_RCODE_SERVFAIL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,6 @@ struct ub_packed_rrset_key {
|
||||
* o base struct
|
||||
* o rr_len size_t array
|
||||
* o rr_data uint8_t* array
|
||||
* o rr_ttl uint32_t array
|
||||
* o rr_data rdata wireformats
|
||||
* o rrsig_data rdata wireformat
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user