]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Compress rrsig owner names.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 27 Apr 2007 13:58:59 +0000 (13:58 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 27 Apr 2007 13:58:59 +0000 (13:58 +0000)
git-svn-id: file:///svn/unbound/trunk@268 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
util/data/dname.c
util/data/dname.h
util/data/msgreply.c

index 6f63c58b000758293f04e5cdbb2c4392a4236d80..8e090c164bddec151d92ef300b1282a9d83f27e4 100644 (file)
@@ -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.
index 32c644fdee5cc353a6b0b999465803f33ade9aad..c532f678c9eb1a466da8130ac01d128228ced43c 100644 (file)
@@ -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);
+       }
+}
index 1a1a60d6da46435332ed950c2f991a71fb9bb716..13723fb16c8285925b08693760ef565c1c8236cf 100644 (file)
@@ -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.
index 0e961051a82c7a4417824fac8fa2b071fd9de6fe..890ffe94eda205696ab1e83b009145dccab34485 100644 (file)
@@ -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; i<data->count; 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; i<total; i++) {
-
-                       /* no compression of dnames yet */
-                       ldns_buffer_write(pkt, key->rk.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]);
                }