]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
compression.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 27 Apr 2007 14:55:47 +0000 (14:55 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 27 Apr 2007 14:55:47 +0000 (14:55 +0000)
git-svn-id: file:///svn/unbound/trunk@269 be551aaa-1e26-0410-a405-d3ace91eadb9

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

index 8e090c164bddec151d92ef300b1282a9d83f27e4..2315a69f59c6d681a8adce32b0c134abd4496f5d 100644 (file)
@@ -2,6 +2,7 @@
        - removed iov usage, it is not good for dns message encoding.
        - owner name compression more optimal.
        - rrsig owner name compression.
+       - rdata domain name compression.
 
 26 April 2007: Wouter
        - floating point exception fix in lock-verify.
index e6a85ede30181c9e22325eca276e57f67ac75e6f..30dfbb3ac2fa4a58b396277ed8f3869cac68d510 100644 (file)
@@ -218,13 +218,11 @@ main(int argc, char* argv[])
        }
        printf("Start of %s unit test.\n", PACKAGE_STRING);
        checklock_start();
-       if(0) {
        net_test();
        alloc_test();
        msgreply_test();
        lruhash_test();
        slabhash_test();
-       }
        msgparse_test();
        checklock_stop();
        printf("%d checks ok.\n", testcount);
index c532f678c9eb1a466da8130ac01d128228ced43c..77848e290ca58a83d86cceb4e19e9f6dfd8b3311 100644 (file)
@@ -349,6 +349,24 @@ dname_count_labels(uint8_t* dname)
        return labs;
 }
 
+int 
+dname_count_size_labels(uint8_t* dname, size_t* size)
+{      
+       uint8_t lablen;
+       int labs = 1;
+       *size = 1;
+
+       lablen = *dname++;
+       while(lablen) {
+               labs++;
+               *size += lablen+1;
+               dname += lablen;
+               lablen = *dname++;
+       }
+       return labs;
+
+}
+
 /**
  * Compare labels in memory, lowercase while comparing.
  * @param p1: label 1
@@ -434,7 +452,8 @@ 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)
+void 
+dname_buffer_write(ldns_buffer* pkt, uint8_t* dname)
 {
        uint8_t lablen;
 
index 13723fb16c8285925b08693760ef565c1c8236cf..d0e5f86fd4b3394e4fa83a0e3e81a106813489a1 100644 (file)
@@ -140,6 +140,14 @@ void dname_print(FILE* out, ldns_buffer* pkt, uint8_t* dname);
  */
 int dname_count_labels(uint8_t* dname);
 
+/**
+ * Count labels and dname length both, for uncompressed dname in memory.
+ * @param dname: pointer to uncompressed dname.
+ * @param size: length of dname, including root label.
+ * @return: count of labels, including root label, "com." has 2 labels.
+ */
+int dname_count_size_labels(uint8_t* dname, size_t* size);
+
 /**
  * Compare dnames, sorted not canonical, but by label.
  * Such that zone contents follows zone apex.
index 890ffe94eda205696ab1e83b009145dccab34485..fb7d78e329a323be05f0f6489a981313d95fe849 100644 (file)
@@ -739,11 +739,10 @@ compress_owner(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
 
 /** compress any domain name to the packet */
 static int
-compress_any_dname(uint8_t* dname, ldns_buffer* pkt, 
+compress_any_dname(uint8_t* dname, ldns_buffer* pkt, int labs, 
        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);
@@ -753,6 +752,67 @@ compress_any_dname(uint8_t* dname, ldns_buffer* pkt,
        return compress_tree_store(tree, dname, labs, pos, region, p);
 }
 
+/** return true if type needs domain name compression in rdata */
+static const ldns_rr_descriptor*
+type_rdata_compressable(struct ub_packed_rrset_key* key)
+{
+       uint16_t t;
+       memmove(&t, &key->rk.dname[key->rk.dname_len], sizeof(t));
+       t = ntohs(t);
+       if(ldns_rr_descript(t) && 
+               ldns_rr_descript(t)->_compress == LDNS_RR_COMPRESS)
+               return ldns_rr_descript(t);
+       return 0;
+}
+
+/** compress domain names in rdata */
+static int
+compress_rdata(ldns_buffer* pkt, uint8_t* rdata, size_t todolen, 
+       region_type* region, struct compress_tree_node** tree, 
+       const ldns_rr_descriptor* desc)
+{
+       int labs, rdf = 0;
+       size_t dname_len, len, pos = ldns_buffer_position(pkt);
+       uint8_t count = desc->_dname_count;
+
+       ldns_buffer_skip(pkt, 2); /* rdata len fill in later */
+       rdata += 2;
+       todolen -= 2;
+       while(todolen > 0 && count) {
+               switch(desc->_wireformat[rdf]) {
+               case LDNS_RDF_TYPE_DNAME:
+                       labs = dname_count_size_labels(rdata, &dname_len);
+                       if(!compress_any_dname(rdata, pkt, labs, region, tree))
+                               return 0;
+                       rdata += dname_len;
+                       todolen -= dname_len;
+                       count--;
+                       len = 0;
+                       break;
+               case LDNS_RDF_TYPE_STR:
+                       len = *rdata + 1;
+                       break;
+               default:
+                       len = get_rdf_size(desc->_wireformat[rdf]);
+               }
+               if(len) {
+                       /* copy over */
+                       ldns_buffer_write(pkt, rdata, len);
+                       todolen -= len;
+                       rdata += len;
+               }
+               rdf++;
+       }
+       /* copy remainder */
+       if(todolen > 0) {
+               ldns_buffer_write(pkt, rdata, todolen);
+       }
+
+       /* set rdata len */
+       ldns_buffer_write_u16_at(pkt, pos, ldns_buffer_position(pkt)-pos-2);
+       return 1;
+}
+
 /** store rrset in iov vector */
 static int
 packed_rrset_iov(struct ub_packed_rrset_key* key, ldns_buffer* pkt, 
@@ -769,6 +829,7 @@ packed_rrset_iov(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
        owner_pos = ldns_buffer_position(pkt);
 
        if(do_data) {
+               const ldns_rr_descriptor* c = type_rdata_compressable(key);
                *num_rrs += data->count;
                for(i=0; i<data->count; i++) {
                        if(1) { /* compression */
@@ -781,7 +842,11 @@ packed_rrset_iov(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
                                        key->rk.dname_len + 4);
                        }
                        ldns_buffer_write_u32(pkt, data->rr_ttl[i]-timenow);
-                       ldns_buffer_write(pkt, data->rr_data[i], 
+                       if(c) {
+                               if(!compress_rdata(pkt, data->rr_data[i],
+                                       data->rr_len[i], region, tree, c))
+                                       return 0;
+                       } else ldns_buffer_write(pkt, data->rr_data[i], 
                                data->rr_len[i]);
                }
        }
@@ -793,8 +858,11 @@ packed_rrset_iov(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
                        if(1) { /* compression */
                                if(owner_ptr)
                                        ldns_buffer_write(pkt, &owner_ptr, 2);
-                               else    compress_any_dname(key->rk.dname, 
-                                               pkt, region, tree);
+                               else    {
+                                       if(!compress_any_dname(key->rk.dname, 
+                                               pkt, owner_labs, region, tree))
+                                               return 0;
+                               }
                        } else {
                                /* no compression */
                                ldns_buffer_write(pkt, key->rk.dname,