From: Wouter Wijngaards Date: Fri, 27 Apr 2007 13:58:59 +0000 (+0000) Subject: Compress rrsig owner names. X-Git-Tag: release-0.3~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=496c39742a236f9dadc6baed349d18024035dd41;p=thirdparty%2Funbound.git Compress rrsig owner names. git-svn-id: file:///svn/unbound/trunk@268 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 6f63c58b0..8e090c164 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,5 +1,7 @@ 27 April 2007: Wouter - removed iov usage, it is not good for dns message encoding. + - owner name compression more optimal. + - rrsig owner name compression. 26 April 2007: Wouter - floating point exception fix in lock-verify. diff --git a/util/data/dname.c b/util/data/dname.c index 32c644fde..c532f678c 100644 --- a/util/data/dname.c +++ b/util/data/dname.c @@ -433,3 +433,17 @@ dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs) } return lastdiff; } + +void dname_buffer_write(ldns_buffer* pkt, uint8_t* dname) +{ + uint8_t lablen; + + lablen = *dname++; + ldns_buffer_write_u8(pkt, lablen); + while(lablen) { + ldns_buffer_write(pkt, dname, lablen); + dname += lablen; + lablen = *dname++; + ldns_buffer_write_u8(pkt, lablen); + } +} diff --git a/util/data/dname.h b/util/data/dname.h index 1a1a60d6d..13723fb16 100644 --- a/util/data/dname.h +++ b/util/data/dname.h @@ -119,6 +119,13 @@ hashvalue_t dname_pkt_hash(ldns_buffer* pkt, uint8_t* dname, hashvalue_t h); */ void dname_pkt_copy(ldns_buffer* pkt, uint8_t* to, uint8_t* dname); +/** + * Copy over a valid dname to a packet. + * @param pkt: packet to copy to. + * @param dname: dname to copy. + */ +void dname_buffer_write(ldns_buffer* pkt, uint8_t* dname); + /** debug helper. Print wireformat dname to output. * @param out: like stdout or a file. * @param pkt: if not NULL, the packet for resolving compression ptrs. diff --git a/util/data/msgreply.c b/util/data/msgreply.c index 0e961051a..890ffe94e 100644 --- a/util/data/msgreply.c +++ b/util/data/msgreply.c @@ -676,61 +676,105 @@ compress_tree_store(struct compress_tree_node** tree, uint8_t* dname, return 1; } -/** bake dname compression */ +/** compress a domain name */ +static void +write_compressed_dname(ldns_buffer* pkt, uint8_t* dname, int labs, + struct compress_tree_node* p) +{ + /* compress it */ + int labcopy = labs - p->labs; + uint8_t lablen; + uint16_t ptr; + + /* copy the first couple of labels */ + while(labcopy--) { + lablen = *dname++; + ldns_buffer_write_u8(pkt, lablen); + ldns_buffer_write(pkt, dname, lablen); + dname += lablen; + } + /* insert compression ptr */ + ptr = (uint16_t)(0xc000 | p->offset); + ldns_buffer_write_u16(pkt, ptr); +} + +/** compress owner name of RR */ static int -bakedname(struct compress_tree_node** tree, region_type* region, - ldns_buffer* pkt, struct packed_rrset_key* rk) +compress_owner(struct ub_packed_rrset_key* key, ldns_buffer* pkt, + region_type* region, struct compress_tree_node** tree, + size_t owner_pos, uint16_t* owner_ptr, int owner_labs) { - /* 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; - uint8_t lablen; - uint8_t* from = rk->dname; - uint16_t ptr; - - /* copy the first couple of labels */ - while(labcopy--) { - lablen = *from++; - ldns_buffer_write_u8(pkt, lablen); - ldns_buffer_write(pkt, from, lablen); - from += lablen; + if(!*owner_ptr) { + /* compress first time dname */ + if((p = compress_tree_lookup(*tree, key->rk.dname, + owner_labs))) { + if(p->labs == owner_labs) + /* avoid ptr chains, since some software is + * not capable of decoding ptr after a ptr. */ + *owner_ptr = htons((uint16_t)(0xc000 | + p->offset)); + write_compressed_dname(pkt, key->rk.dname, + owner_labs, p); + ldns_buffer_write(pkt, &key->rk.dname[ + key->rk.dname_len], 4); + } else { + /* no compress */ + ldns_buffer_write(pkt, key->rk.dname, + key->rk.dname_len+4); + if(owner_pos <= PTR_MAX_OFFSET) + *owner_ptr = htons((uint16_t)(0xc000 | + owner_pos)); } - /* insert compression ptr */ - ptr = (uint16_t)(0xc000 | p->offset); - ldns_buffer_write_u16(pkt, ptr); + if(!compress_tree_store(tree, key->rk.dname, + owner_labs, owner_pos, region, p)) + return 0; } else { - /* uncompressed */ - ldns_buffer_write(pkt, rk->dname, rk->dname_len); + /* always compress 2nd-further RRs in RRset */ + ldns_buffer_write(pkt, owner_ptr, 2); + ldns_buffer_write(pkt, &key->rk.dname[key->rk.dname_len], 4); } - - /* store this name for future compression */ - if(!compress_tree_store(tree, rk->dname, labs, pos, region, p)) - return 0; return 1; } +/** compress any domain name to the packet */ +static int +compress_any_dname(uint8_t* dname, ldns_buffer* pkt, + region_type* region, struct compress_tree_node** tree) +{ + struct compress_tree_node* p; + int labs = dname_count_labels(dname); + size_t pos = ldns_buffer_position(pkt); + if((p = compress_tree_lookup(*tree, dname, labs))) { + write_compressed_dname(pkt, dname, labs, p); + } else { + dname_buffer_write(pkt, dname); + } + return compress_tree_store(tree, dname, labs, pos, region, p); +} + /** store rrset in iov vector */ static int 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; + size_t i, owner_pos; + int owner_labs; + uint16_t owner_ptr = 0; struct packed_rrset_data* data = (struct packed_rrset_data*) key->entry.data; + + owner_labs = dname_count_labels(key->rk.dname); + owner_pos = ldns_buffer_position(pkt); + if(do_data) { *num_rrs += data->count; for(i=0; icount; i++) { if(1) { /* compression */ - if(!bakedname(tree, region, pkt, &key->rk)) + if(!compress_owner(key, pkt, region, tree, + owner_pos, &owner_ptr, owner_labs)) return 0; - ldns_buffer_write(pkt, - &key->rk.dname[key->rk.dname_len], 4); } else { /* no compression */ ldns_buffer_write(pkt, key->rk.dname, @@ -746,14 +790,22 @@ packed_rrset_iov(struct ub_packed_rrset_key* key, ldns_buffer* pkt, size_t total = data->count+data->rrsig_count; *num_rrs += data->rrsig_count; for(i=data->count; irk.dname, - key->rk.dname_len); + if(1) { /* compression */ + if(owner_ptr) + ldns_buffer_write(pkt, &owner_ptr, 2); + else compress_any_dname(key->rk.dname, + pkt, region, tree); + } else { + /* no compression */ + 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); + /* rrsig rdata cannot be compressed, perform 100+ byte + * memcopy. */ ldns_buffer_write(pkt, data->rr_data[i], data->rr_len[i]); }