mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-01-01 12:29:36 -05:00
no more iov per rr.
git-svn-id: file:///svn/unbound/trunk@266 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
87bff3dc63
commit
1bffcab1f3
5 changed files with 92 additions and 161 deletions
|
|
@ -1,3 +1,6 @@
|
|||
27 April 2007: Wouter
|
||||
- removed iov usage, it is not good for dns message encoding.
|
||||
|
||||
26 April 2007: Wouter
|
||||
- floating point exception fix in lock-verify.
|
||||
- lint uses make dependency
|
||||
|
|
|
|||
4
doc/TODO
4
doc/TODO
|
|
@ -12,5 +12,7 @@ o possible optimization, so that precious id number resource is not depleted
|
|||
special id numbers, and if you release the next_id number for the thread
|
||||
it reuses that id number.
|
||||
o use rbtree to compress domain names in messages, sorted AXFRs of 16Kb
|
||||
and so on. This may be faster for that case.
|
||||
and so on. For current packets, even worstcase, list, is ok. Only if we
|
||||
start to send out compressed AXFRs then it becomes a problem.
|
||||
We can cap AXFR packets on 256 or 1024 domain names, for example.
|
||||
o speed up pkt domain name decompression loop detection using counter perhaps.
|
||||
|
|
|
|||
|
|
@ -253,8 +253,6 @@ testpkt(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out,
|
|||
uint16_t flags;
|
||||
uint32_t timenow = 0;
|
||||
region_type *region = region_create(malloc, free);
|
||||
struct iovec iov[1024];
|
||||
size_t maxiov = 1024;
|
||||
|
||||
hex_to_buf(pkt, hex);
|
||||
memmove(&id, ldns_buffer_begin(pkt), sizeof(id));
|
||||
|
|
@ -268,11 +266,11 @@ testpkt(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out,
|
|||
checkformerr(pkt);
|
||||
unit_assert(ret != LDNS_RCODE_SERVFAIL);
|
||||
} else {
|
||||
sz = reply_info_iov_regen(&qi, rep, id, flags, iov, maxiov,
|
||||
timenow, region);
|
||||
sz = reply_info_encode(&qi, rep, id, flags, out, timenow,
|
||||
region);
|
||||
unit_assert(sz != 0); /* udp packets should fit in 1024 iov */
|
||||
write_iov_buffer(out, iov, sz);
|
||||
if(vbmp) printf("iov len outlen %u %u\n", (unsigned)sz,
|
||||
if(vbmp) printf("inlen %u outlen %u\n",
|
||||
(unsigned)ldns_buffer_limit(pkt),
|
||||
(unsigned)ldns_buffer_limit(out));
|
||||
test_buffers(pkt, out);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -676,149 +676,86 @@ compress_tree_store(struct compress_tree_node** tree, uint8_t* dname,
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** bake a new type-class-ttl value, or 0 on malloc error */
|
||||
static uint32_t*
|
||||
bake_tcttl(int do_sig, region_type* region,
|
||||
struct packed_rrset_key* rk, uint32_t ttl, uint32_t timenow,
|
||||
uint32_t* prevttl, uint32_t* prevtcttl)
|
||||
{
|
||||
/* type, class, ttl,
|
||||
type-class-ttl used for rrsigs.
|
||||
ttl used for data itself. */
|
||||
uint32_t* t;
|
||||
if(prevttl && *prevttl == ttl)
|
||||
return prevtcttl;
|
||||
if(do_sig) {
|
||||
t = (uint32_t*)region_alloc(region, 2*sizeof(uint32_t));
|
||||
if(!t) return 0;
|
||||
((uint16_t*)t)[0] = htons(LDNS_RR_TYPE_RRSIG);
|
||||
memcpy( &(((uint16_t*)t)[1]), &(rk->dname[rk->dname_len+2]),
|
||||
sizeof(uint16_t));
|
||||
t[1] = htonl(ttl - timenow);
|
||||
} else {
|
||||
t = (uint32_t*)region_alloc(region, sizeof(uint32_t));
|
||||
if(!t) return 0;
|
||||
t[0] = htonl(ttl - timenow);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
/** bake dname iov */
|
||||
/** bake dname compression */
|
||||
static int
|
||||
bakedname(int dosig, struct compress_tree_node** tree, size_t* offset,
|
||||
region_type* region, struct iovec* iov, struct packed_rrset_key* rk)
|
||||
bakedname(struct compress_tree_node** tree, region_type* region,
|
||||
ldns_buffer* pkt, struct packed_rrset_key* rk)
|
||||
{
|
||||
/* see if this name can be compressed */
|
||||
size_t pos = ldns_buffer_position(pkt);
|
||||
struct compress_tree_node* p;
|
||||
int labs = dname_count_labels(rk->dname);
|
||||
p = compress_tree_lookup(*tree, rk->dname, labs);
|
||||
if(p && p->offset <= PTR_MAX_OFFSET) {
|
||||
/* compress it */
|
||||
int labcopy = labs - p->labs;
|
||||
size_t len = 0;
|
||||
uint8_t lablen;
|
||||
uint8_t* from = rk->dname;
|
||||
uint16_t ptr;
|
||||
uint8_t* dat = (uint8_t*)region_alloc(region,
|
||||
(dosig?0:sizeof(uint16_t)*2) + rk->dname_len);
|
||||
/* note: oversized memory allocation. */
|
||||
if(!dat) return 0;
|
||||
iov->iov_base = dat;
|
||||
|
||||
/* copy the first couple of labels */
|
||||
while(labcopy--) {
|
||||
lablen = *from++;
|
||||
*dat++ = lablen;
|
||||
memmove(dat, from, lablen);
|
||||
len += lablen+1;
|
||||
dat += lablen;
|
||||
ldns_buffer_write_u8(pkt, lablen);
|
||||
ldns_buffer_write(pkt, from, lablen);
|
||||
from += lablen;
|
||||
}
|
||||
/* insert compression ptr */
|
||||
ptr = (uint16_t)(0xc000 | p->offset);
|
||||
ptr = htons(ptr);
|
||||
memmove(dat, &ptr, sizeof(ptr));
|
||||
len += sizeof(ptr);
|
||||
dat += sizeof(ptr);
|
||||
if(!dosig) {
|
||||
/* add type and class */
|
||||
memmove(dat, &rk->dname[rk->dname_len], 4);
|
||||
dat += 4;
|
||||
len += 4;
|
||||
}
|
||||
log_assert(len <= (dosig?0:sizeof(uint16_t)*2) + rk->dname_len);
|
||||
iov->iov_len = len;
|
||||
ldns_buffer_write_u16(pkt, ptr);
|
||||
} else {
|
||||
/* uncompressed */
|
||||
iov->iov_base = rk->dname;
|
||||
if(dosig)
|
||||
iov->iov_len = rk->dname_len;
|
||||
else iov->iov_len = rk->dname_len + 4;
|
||||
ldns_buffer_write(pkt, rk->dname, rk->dname_len);
|
||||
}
|
||||
|
||||
/* store this name for future compression */
|
||||
if(!compress_tree_store(tree, rk->dname, labs, *offset, region, p))
|
||||
if(!compress_tree_store(tree, rk->dname, labs, pos, region, p))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** store rrset in iov vector */
|
||||
static int
|
||||
packed_rrset_iov(struct ub_packed_rrset_key* key, struct iovec* iov,
|
||||
size_t max, uint16_t* num_rrs, uint32_t timenow, region_type* region,
|
||||
size_t* used, int do_data, int do_sig,
|
||||
struct compress_tree_node** tree, size_t* offset)
|
||||
packed_rrset_iov(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
|
||||
uint16_t* num_rrs, uint32_t timenow, region_type* region,
|
||||
int do_data, int do_sig, struct compress_tree_node** tree)
|
||||
{
|
||||
size_t i;
|
||||
uint32_t* tcttl = 0;
|
||||
struct packed_rrset_data* data = (struct packed_rrset_data*)
|
||||
key->entry.data;
|
||||
if(do_data) {
|
||||
*num_rrs += data->count;
|
||||
for(i=0; i<data->count; i++) {
|
||||
if(max - *used < 3) return 0;
|
||||
if(!(tcttl = bake_tcttl(0, region, &key->rk,
|
||||
data->rr_ttl[i], timenow,
|
||||
i>0?&data->rr_ttl[i-1]:0, tcttl)))
|
||||
return 0;
|
||||
/* no compression of dnames yet */
|
||||
if(1) {
|
||||
if(!bakedname(0, tree, offset, region, &iov[*used],
|
||||
&key->rk))
|
||||
return 0;
|
||||
if(1) { /* compression */
|
||||
if(!bakedname(tree, region, pkt, &key->rk))
|
||||
return 0;
|
||||
ldns_buffer_write(pkt,
|
||||
&key->rk.dname[key->rk.dname_len], 4);
|
||||
} else {
|
||||
/* no compression */
|
||||
iov[*used].iov_base = (void*)key->rk.dname;
|
||||
iov[*used].iov_len = key->rk.dname_len + 4;
|
||||
ldns_buffer_write(pkt, key->rk.dname,
|
||||
key->rk.dname_len + 4);
|
||||
}
|
||||
iov[*used+1].iov_base = (void*)tcttl;
|
||||
iov[*used+1].iov_len = sizeof(uint32_t);
|
||||
iov[*used+2].iov_base = (void*)data->rr_data[i];
|
||||
iov[*used+2].iov_len = data->rr_len[i];
|
||||
*offset += iov[*used].iov_len + sizeof(uint32_t) +
|
||||
data->rr_len[i];
|
||||
*used += 3;
|
||||
ldns_buffer_write_u32(pkt, data->rr_ttl[i]-timenow);
|
||||
ldns_buffer_write(pkt, data->rr_data[i],
|
||||
data->rr_len[i]);
|
||||
}
|
||||
}
|
||||
/* insert rrsigs */
|
||||
if(do_sig) {
|
||||
size_t total = data->count+data->rrsig_count;
|
||||
*num_rrs += data->rrsig_count;
|
||||
for(i=0; i<data->rrsig_count; i++) {
|
||||
if(max - *used < 3) return 0;
|
||||
if(!(tcttl = bake_tcttl(1, region, &key->rk,
|
||||
data->rr_ttl[data->count+i], timenow,
|
||||
i>0?&data->rr_ttl[i-1]:0, tcttl)))
|
||||
return 0;
|
||||
for(i=data->count; i<total; i++) {
|
||||
|
||||
/* no compression of dnames yet */
|
||||
iov[*used].iov_base = (void*)key->rk.dname;
|
||||
iov[*used].iov_len = key->rk.dname_len;
|
||||
iov[*used+1].iov_base = (void*)tcttl;
|
||||
iov[*used+1].iov_len = sizeof(uint32_t)*2;
|
||||
iov[*used+2].iov_base = (void*)data->rr_data[data->count+i];
|
||||
iov[*used+2].iov_len = data->rr_len[data->count+i];
|
||||
*offset += iov[*used].iov_len + sizeof(uint32_t)*2 +
|
||||
data->rr_len[data->count+i];
|
||||
*used += 3;
|
||||
ldns_buffer_write(pkt, key->rk.dname,
|
||||
key->rk.dname_len);
|
||||
ldns_buffer_write_u16(pkt, LDNS_RR_TYPE_RRSIG);
|
||||
ldns_buffer_write(pkt, &(key->rk.dname[
|
||||
key->rk.dname_len+2]), sizeof(uint16_t));
|
||||
ldns_buffer_write_u32(pkt, data->rr_ttl[i]-timenow);
|
||||
ldns_buffer_write(pkt, data->rr_data[i],
|
||||
data->rr_len[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -828,90 +765,81 @@ packed_rrset_iov(struct ub_packed_rrset_key* key, struct iovec* iov,
|
|||
/** store msg section in iov vector */
|
||||
static int
|
||||
insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
|
||||
struct iovec* iov, size_t max, size_t rrsets_before,
|
||||
uint32_t timenow, region_type* region, size_t* used, int addit,
|
||||
struct compress_tree_node** tree, size_t* offset)
|
||||
ldns_buffer* pkt, size_t rrsets_before, uint32_t timenow,
|
||||
region_type* region, int addit, struct compress_tree_node** tree)
|
||||
{
|
||||
size_t i;
|
||||
*num_rrs = 0;
|
||||
if(!addit) {
|
||||
for(i=0; i<num_rrsets; i++)
|
||||
if(!packed_rrset_iov(rep->rrsets[rrsets_before+i], iov,
|
||||
max, num_rrs, timenow, region, used, 1, 1,
|
||||
tree, offset))
|
||||
if(!packed_rrset_iov(rep->rrsets[rrsets_before+i], pkt,
|
||||
num_rrs, timenow, region, 1, 1, tree))
|
||||
return 0;
|
||||
} else {
|
||||
for(i=0; i<num_rrsets; i++)
|
||||
if(!packed_rrset_iov(rep->rrsets[rrsets_before+i], iov,
|
||||
max, num_rrs, timenow, region, used, 1, 0,
|
||||
tree, offset))
|
||||
if(!packed_rrset_iov(rep->rrsets[rrsets_before+i], pkt,
|
||||
num_rrs, timenow, region, 1, 0, tree))
|
||||
return 0;
|
||||
for(i=0; i<num_rrsets; i++)
|
||||
if(!packed_rrset_iov(rep->rrsets[rrsets_before+i], iov,
|
||||
max, num_rrs, timenow, region, used, 0, 1,
|
||||
tree, offset))
|
||||
if(!packed_rrset_iov(rep->rrsets[rrsets_before+i], pkt,
|
||||
num_rrs, timenow, region, 0, 1, tree))
|
||||
return 0;
|
||||
}
|
||||
*num_rrs = htons(*num_rrs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t reply_info_iov_regen(struct query_info* qinfo, struct reply_info* rep,
|
||||
uint16_t id, uint16_t flags, struct iovec* iov, size_t max,
|
||||
uint32_t timenow, region_type* region)
|
||||
int reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
||||
uint16_t id, uint16_t flags, ldns_buffer* buffer, uint32_t timenow,
|
||||
region_type* region)
|
||||
{
|
||||
size_t used;
|
||||
uint16_t* hdr = (uint16_t*)region_alloc(region, sizeof(uint16_t)*6);
|
||||
size_t offset = 0;
|
||||
uint16_t ancount=0, nscount=0, arcount=0;
|
||||
struct compress_tree_node* tree = 0;
|
||||
if(!hdr) return 0;
|
||||
if(max<1) return 0;
|
||||
hdr[0] = id;
|
||||
hdr[1] = htons(flags);
|
||||
iov[0].iov_base = (void*)&hdr[0];
|
||||
iov[0].iov_len = sizeof(uint16_t)*6;
|
||||
hdr[2] = htons(rep->qdcount);
|
||||
offset = sizeof(uint16_t)*6;
|
||||
used=1;
|
||||
|
||||
ldns_buffer_clear(buffer);
|
||||
if(ldns_buffer_capacity(buffer) < LDNS_HEADER_SIZE)
|
||||
return 0;
|
||||
|
||||
ldns_buffer_write(buffer, &id, sizeof(uint16_t));
|
||||
ldns_buffer_write_u16(buffer, flags);
|
||||
ldns_buffer_write_u16(buffer, rep->qdcount);
|
||||
/* skip an, ns, ar counts */
|
||||
ldns_buffer_set_position(buffer, LDNS_HEADER_SIZE);
|
||||
|
||||
/* insert query section */
|
||||
if(rep->qdcount) {
|
||||
uint16_t* qt = (uint16_t*)region_alloc(region,sizeof(uint16_t));
|
||||
uint16_t* qc = (uint16_t*)region_alloc(region,sizeof(uint16_t));
|
||||
if(!qt || !qc) return 0;
|
||||
if(max-used < 3) return 0;
|
||||
iov[used].iov_base = (void*)qinfo->qname;
|
||||
iov[used].iov_len = qinfo->qnamesize;
|
||||
if(ldns_buffer_remaining(buffer) <
|
||||
qinfo->qnamesize+sizeof(uint16_t)*2)
|
||||
return 0; /* buffer too small */
|
||||
if(!compress_tree_store(&tree, qinfo->qname,
|
||||
dname_count_labels(qinfo->qname), offset, region, NULL))
|
||||
dname_count_labels(qinfo->qname),
|
||||
ldns_buffer_position(buffer), region, NULL))
|
||||
return 0;
|
||||
*qt = htons(qinfo->qtype);
|
||||
*qc = htons(qinfo->qclass);
|
||||
iov[used+1].iov_base = (void*)qt;
|
||||
iov[used+1].iov_len = sizeof(uint16_t);
|
||||
iov[used+2].iov_base = (void*)qc;
|
||||
iov[used+2].iov_len = sizeof(uint16_t);
|
||||
offset += qinfo->qnamesize + sizeof(uint16_t)*2;
|
||||
used += 3;
|
||||
ldns_buffer_write(buffer, qinfo->qname, qinfo->qnamesize);
|
||||
ldns_buffer_write_u16(buffer, qinfo->qtype);
|
||||
ldns_buffer_write_u16(buffer, qinfo->qclass);
|
||||
}
|
||||
|
||||
/* insert answer section */
|
||||
if(!insert_section(rep, rep->an_numrrsets, &hdr[3], iov, max,
|
||||
0, timenow, region, &used, 0, &tree, &offset))
|
||||
if(!insert_section(rep, rep->an_numrrsets, &ancount, buffer,
|
||||
0, timenow, region, 0, &tree))
|
||||
return 0;
|
||||
ldns_buffer_write_u16_at(buffer, 6, ancount);
|
||||
|
||||
/* insert auth section */
|
||||
if(!insert_section(rep, rep->ns_numrrsets, &hdr[4], iov, max,
|
||||
rep->an_numrrsets, timenow, region, &used, 0, &tree, &offset))
|
||||
if(!insert_section(rep, rep->ns_numrrsets, &nscount, buffer,
|
||||
rep->an_numrrsets, timenow, region, 0, &tree))
|
||||
return 0;
|
||||
ldns_buffer_write_u16_at(buffer, 8, nscount);
|
||||
|
||||
/* insert add section */
|
||||
if(!insert_section(rep, rep->ar_numrrsets, &hdr[5], iov, max,
|
||||
if(!insert_section(rep, rep->ar_numrrsets, &arcount, buffer,
|
||||
rep->an_numrrsets + rep->ns_numrrsets, timenow, region,
|
||||
&used, 1, &tree, &offset))
|
||||
1, &tree))
|
||||
return 0;
|
||||
ldns_buffer_write_u16_at(buffer, 10, arcount);
|
||||
ldns_buffer_flip(buffer);
|
||||
|
||||
return used;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -251,20 +251,20 @@ void reply_info_answer(struct reply_info* rep, uint16_t qflags,
|
|||
ldns_buffer* buf);
|
||||
|
||||
/**
|
||||
* Regenerate the wireformat from the parsed msg.
|
||||
* Regenerate the wireformat from the stored msg reply.
|
||||
* @param qinfo: query info to store.
|
||||
* @param rep: reply to store.
|
||||
* @param id: id value to store, network order.
|
||||
* @param flags: flags value to store, host order.
|
||||
* @param iov: iov to store it into (start position to store).
|
||||
* @param max: max that can be stored.
|
||||
* @param buffer: buffer to store the packet into.
|
||||
* @param timenow: time now, to adjust ttl values.
|
||||
* @param region: to store temporary data in.
|
||||
* @return: number of items stored, 0 on error.
|
||||
* @return: nonzero is success, or
|
||||
* 0 on error: malloc failure or buffer too small.
|
||||
*/
|
||||
size_t reply_info_iov_regen(struct query_info* qinfo, struct reply_info* rep,
|
||||
uint16_t id, uint16_t flags, struct iovec* iov, size_t max,
|
||||
uint32_t timenow, struct region* region);
|
||||
int reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
||||
uint16_t id, uint16_t flags, ldns_buffer* buffer, uint32_t timenow,
|
||||
struct region* region);
|
||||
|
||||
/**
|
||||
* Generate and send out answer from reply_info.
|
||||
|
|
|
|||
Loading…
Reference in a new issue