]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Acknowledge use of unbound-java code in iterator. Nicer readme.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 25 May 2007 12:02:37 +0000 (12:02 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 25 May 2007 12:02:37 +0000 (12:02 +0000)
       - services/cache/dns.c DNS Cache. Hybrid cache uses msgcache and
         rrset cache from module environment.
       - packed rrset key has type and class as easily accessable struct
         members. They are still kept in network format for fast msg encode.
       - dns cache find_delegation routine.

git-svn-id: file:///svn/unbound/trunk@339 be551aaa-1e26-0410-a405-d3ace91eadb9

13 files changed:
doc/Changelog
doc/README
iterator/iterator.c
services/cache/dns.c [new file with mode: 0644]
services/cache/dns.h [new file with mode: 0644]
services/cache/rrset.c
services/cache/rrset.h
services/outside_network.c
util/data/msgparse.c
util/data/msgreply.c
util/data/packed_rrset.c
util/data/packed_rrset.h
util/net_help.h

index 3a089a518ab2d8efbcbca8bdc0822a3cdf5c4f44..d009617cb7d35bf200180cc5d2f7681ac68b37db 100644 (file)
@@ -1,3 +1,11 @@
+25 May 2007: Wouter
+       - Acknowledge use of unbound-java code in iterator. Nicer readme.
+       - services/cache/dns.c DNS Cache. Hybrid cache uses msgcache and
+         rrset cache from module environment.
+       - packed rrset key has type and class as easily accessable struct
+         members. They are still kept in network format for fast msg encode.
+       - dns cache find_delegation routine.
+
 24 May 2007: Wouter
        - small changes to prepare for subqueries.
        - iterator forwarder feature separated out.
index c1bb61b83f7457249e834e384f530205d004559a..3fc47c6e674154acb32b9c985bc58060e4944046 100644 (file)
@@ -4,19 +4,27 @@ http://unbound.net
 
 This software is under BSD license, see LICENSE for details.
 
+* Download the latest version of this software from 
+       http://unbound.net 
+  or get a beta version from the svn repository at 
+       http://unbound.net/svn/
+
 * Needs the following libraries
   * ldns       http://www.nlnetlabs.nl/ldns/                   (BSD license)
   * libevent   http://www.monkey.org/~provos/libevent/         (BSD license)
 
+* Create build environment 
+  * run libtoolize -c if config.sub is missing.
+  * autoreconf (autoheader && autoconf), if ./configure is missing.
+
 * Make and install: ./configure; make
   * --with-ldns=/path/to/ldns
   * --with-libevent=/path/to/libevent
        Can be set to either the system install or the build directory.
-       --with-libevent=no gives an alternative to libevent (based on select).
-
-* Create build environment 
-  * run libtoolize -c if config.sub is missing.
-  * autoreconf (autoheader && autoconf), if ./configure is missing.
+       --with-libevent=no gives a builtin alternative implementation.
+  * --without-pthreads 
+       This disables pthreads, and uses Solaris thr library or no threading. 
+       Without this option the pthreads library is detected automatically.
 
 Known issues
 ------------
@@ -25,4 +33,11 @@ o If libevent is older (1.3 and before), unbound will exit instead of reload
   printed. Perform ./configure --with-libevent=no or update libevent, rerun 
   configure and recompile unbound to make sighup work correctly.
 
+Acknowledgements
+----------------
+o Thanks to David Blacka and Matt Larson (Verisign) for the unbound-java
+  prototype. Design and code from that prototype has been used to create
+  this program. Such as the iterator state machine and the cache design.
+o See Credits file for contributors.
+
 * mailto:wouter@nlnetlabs.nl
index 2e425761e3b44f82cb73cdc74de2df0298a85500..19f6f8fcaa1b620826be4c44e5473bb00722128e 100644 (file)
 
 #include "config.h"
 #include "iterator/iterator.h"
+#include "iterator/iter_utils.h"
+#include "iterator/iter_hints.h"
+#include "services/cache/dns.h"
 #include "util/module.h"
 #include "util/netevent.h"
 #include "util/net_help.h"
-#include "util/storage/slabhash.h"
 #include "util/region-allocator.h"
-#include "services/cache/rrset.h"
-#include "iterator/iter_utils.h"
-#include "iterator/iter_hints.h"
 
 /** iterator init */
 static int 
@@ -83,45 +82,6 @@ iter_deinit(struct module_env* env, int id)
                free(iter_env);
 }
 
-/** store rrsets in the rrset cache. */
-static void
-store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now)
-{
-        size_t i;
-        /* see if rrset already exists in cache, if not insert it. */
-        for(i=0; i<rep->rrset_count; i++) {
-                rep->ref[i].key = rep->rrsets[i];
-                rep->ref[i].id = rep->rrsets[i]->id;
-               if(rrset_cache_update(env->rrset_cache, &rep->ref[i], 
-                       env->alloc, now)) /* it was in the cache */
-                       rep->rrsets[i] = rep->ref[i].key;
-        }
-}
-
-
-/** store message in the cache */
-static void
-store_msg(struct module_qstate* qstate, struct query_info* qinfo,
-       struct reply_info* rep)
-{
-       struct msgreply_entry* e;
-       uint32_t now = time(NULL);
-       reply_info_set_ttls(rep, now);
-       store_rrsets(qstate->env, rep, now);
-       if(rep->ttl == 0) {
-               log_info("TTL 0: dropped msg from cache");
-               return;
-       }
-       reply_info_sortref(rep);
-       /* store msg in the cache */
-       if(!(e = query_info_entrysetup(qinfo, rep, qstate->query_hash))) {
-               log_err("store_msg: malloc failed");
-               return;
-       }
-       slabhash_insert(qstate->env->msg_cache, qstate->query_hash,
-               &e->entry, rep, &qstate->env->alloc);
-}
-
 /** new query for iterator */
 static int
 iter_new(struct module_qstate* qstate, int id)
@@ -175,7 +135,8 @@ iter_handlereply(struct module_qstate* qstate, int id,
                qstate->query_flags, qstate->buf, 0, 0, 
                qstate->scratch, us, &qstate->edns))
                return 0;
-       store_msg(qstate, &reply_qinfo, reply_msg);
+       dns_cache_store_msg(qstate->env, &reply_qinfo, qstate->query_hash, 
+               reply_msg);
        qstate->ext_state[id] = module_finished;
        return 1;
 }
diff --git a/services/cache/dns.c b/services/cache/dns.c
new file mode 100644 (file)
index 0000000..bf10c3d
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * services/cache/dns.c - Cache services for DNS using msg and rrset caches.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains the DNS cache.
+ */
+#include "config.h"
+#include "iterator/iter_delegpt.h"
+#include "services/cache/dns.h"
+#include "services/cache/rrset.h"
+#include "util/data/msgreply.h"
+#include "util/data/packed_rrset.h"
+#include "util/module.h"
+#include "util/net_help.h"
+
+/** store rrsets in the rrset cache. */
+static void
+store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now)
+{
+        size_t i;
+        /* see if rrset already exists in cache, if not insert it. */
+        for(i=0; i<rep->rrset_count; i++) {
+                rep->ref[i].key = rep->rrsets[i];
+                rep->ref[i].id = rep->rrsets[i]->id;
+                if(rrset_cache_update(env->rrset_cache, &rep->ref[i],
+                        env->alloc, now)) /* it was in the cache */
+                        rep->rrsets[i] = rep->ref[i].key;
+        }
+}
+
+void 
+dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
+       hashvalue_t hash, struct reply_info* rep)
+{
+       struct msgreply_entry* e;
+       uint32_t now = time(NULL);
+
+       /* store RRsets */
+       reply_info_set_ttls(rep, now);
+       store_rrsets(env, rep, now);
+       if(rep->ttl == 0) {
+               /* we do not store the message, but we did store the RRs,
+                * which could be useful for delegation information */
+               verbose(VERB_ALGO, "TTL 0: dropped msg from cache");
+               return;
+       }
+
+       /* store msg in the cache */
+       reply_info_sortref(rep);
+       if(!(e = query_info_entrysetup(qinfo, rep, hash))) {
+               log_err("store_msg: malloc failed");
+               return;
+       }
+       slabhash_insert(env->msg_cache, hash, &e->entry, rep, env->alloc);
+}
+
+/** find closest NS and returns the rrset (locked) */
+static struct ub_packed_rrset_key*
+find_deleg_ns(struct module_env* env, uint8_t* qname, size_t qnamelen, 
+       uint16_t qclass, uint32_t now)
+{
+       struct ub_packed_rrset_key *rrset;
+       uint8_t lablen;
+
+       /* snip off front part of qname until NS is found */
+       while(qnamelen > 0) {
+               if((rrset = rrset_cache_lookup(env->rrset_cache, qname, 
+                       qnamelen, LDNS_RR_TYPE_NS, qclass, 0, now, 0)))
+                       return rrset;
+
+               /* snip off front label */
+               lablen = *qname;
+               qname += lablen + 1;
+               qnamelen -= lablen + 1;
+       }
+       return NULL;
+}
+
+/** add A records to delegation */
+static int
+add_a(struct ub_packed_rrset_key* ak, struct delegpt* dp, 
+       struct region* region)
+{
+       struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
+       size_t i;
+       struct sockaddr_in sa;
+       socklen_t len = (socklen_t)sizeof(sa);
+       memset(&sa, 0, len);
+       sa.sin_family = AF_INET;
+       sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
+       for(i=0; i<d->count; i++) {
+               if(d->rr_len[i] != 2 + INET_SIZE)
+                       continue;
+               memmove(&sa.sin_addr, d->rr_data[i]+2, INET_SIZE);
+               log_addr("adding A to deleg",  (struct sockaddr_storage*)&sa,
+                       len);
+               if(!delegpt_add_target(dp, region, ak->rk.dname, 
+                       ak->rk.dname_len, (struct sockaddr_storage*)&sa,
+                       len))
+                       return 0;
+       }
+       return 1;
+}
+
+/** add AAAA records to delegation */
+static int
+add_aaaa(struct ub_packed_rrset_key* ak, struct delegpt* dp, 
+       struct region* region)
+{
+       struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
+       size_t i;
+       struct sockaddr_in6 sa;
+       socklen_t len = (socklen_t)sizeof(sa);
+       memset(&sa, 0, len);
+       sa.sin6_family = AF_INET6;
+       sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
+       for(i=0; i<d->count; i++) {
+               if(d->rr_len[i] != 2 + INET6_SIZE) /* rdatalen + len of IP6 */
+                       continue;
+               memmove(&sa.sin6_addr, d->rr_data[i]+2, INET6_SIZE);
+               log_addr("adding AAAA to deleg",  (struct sockaddr_storage*)&sa,
+                       len);
+               if(!delegpt_add_target(dp, region, ak->rk.dname, 
+                       ak->rk.dname_len, (struct sockaddr_storage*)&sa,
+                       len))
+                       return 0;
+       }
+       return 1;
+}
+
+/** find and add A and AAAA records for nameservers in delegpt */
+static int
+find_add_addrs(struct module_env* env, uint16_t qclass, struct region* region,
+       struct delegpt* dp, uint32_t now)
+{
+       struct delegpt_ns* ns;
+       struct ub_packed_rrset_key* akey;
+       for(ns = dp->nslist; ns; ns = ns->next) {
+               akey = rrset_cache_lookup(env->rrset_cache, ns->name, 
+                       ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
+               if(akey) {
+                       if(!add_a(akey, dp, region)) {
+                               lock_rw_unlock(akey->entry.lock);
+                               return 0;
+                       }
+                       lock_rw_unlock(akey->entry.lock);
+               }
+               akey = rrset_cache_lookup(env->rrset_cache, ns->name, 
+                       ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
+               if(akey) {
+                       if(!add_aaaa(akey, dp, region)) {
+                               lock_rw_unlock(akey->entry.lock);
+                               return 0;
+                       }
+                       lock_rw_unlock(akey->entry.lock);
+               }
+       }
+       return 1;
+}
+
+struct delegpt* 
+dns_cache_find_delegation(struct module_env* env, uint8_t* qname, 
+       size_t qnamelen, uint16_t qclass, struct region* region)
+{
+       /* try to find closest NS rrset */
+       struct ub_packed_rrset_key* nskey;
+       struct packed_rrset_data* nsdata;
+       struct delegpt* dp;
+       size_t i;
+       uint32_t now = (uint32_t)time(NULL);
+
+       nskey = find_deleg_ns(env, qname, qnamelen, qclass, now);
+       if(!nskey) /* hope the caller has hints to prime or something */
+               return NULL;
+       nsdata = (struct packed_rrset_data*)nskey->entry.data;
+       /* got the NS key, create delegation point */
+       dp = delegpt_create(region);
+       if(!dp || !delegpt_set_name(dp, region, nskey->rk.dname)) {
+               lock_rw_unlock(nskey->entry.lock);
+               log_err("find_delegation: out of memory");
+               return NULL;
+       }
+       /* add NS entries */
+       for(i=0; i<nsdata->count; i++) {
+               if(nsdata->rr_len[i] < 2+1) continue; /* len + root label */
+               /* add rdata of NS (= wirefmt dname), skip rdatalen bytes */
+               if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2))
+                       log_err("find_delegation: addns out of memory");
+       }
+       /* find and add A entries */
+       lock_rw_unlock(nskey->entry.lock); /* first unlock before next lookup*/
+       if(!find_add_addrs(env, qclass, region, dp, now))
+               log_err("find_delegation: addrs out of memory");
+       log_info("dns_cache_find_delegation returns delegpt");
+       delegpt_log(dp);
+       return dp;
+}
diff --git a/services/cache/dns.h b/services/cache/dns.h
new file mode 100644 (file)
index 0000000..4da5170
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * services/cache/dns.h - Cache services for DNS using msg and rrset caches.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains the DNS cache.
+ */
+
+#ifndef SERVICES_CACHE_DNS_H
+#define SERVICES_CACHE_DNS_H
+#include "util/storage/lruhash.h"
+struct module_env;
+struct query_info;
+struct reply_info;
+struct region;
+struct delegpt;
+
+/**
+ * Store message in the cache. Stores in message cache and rrset cache.
+ * Both qinfo and rep should be malloced and are put in the cache.
+ * They should not be used after this call, as they are then in shared cache.
+ * Does not return errors, they are logged and only lead to less cache.
+ *
+ * @param env: module environment with the DNS cache.
+ * @param qinfo: query info
+ * @param hash: hash over qinfo.
+ * @param rep: reply info, together with qinfo makes up the message.
+ *     Adjusts the reply info TTLs to absolute time.
+ */
+void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
+       hashvalue_t hash, struct reply_info* rep);
+
+/**
+ * Find a delegation from the cache.
+ * @param env: module environment with the DNS cache.
+ * @param qname: query name.
+ * @param qnamelen: length of qname.
+ * @param qclass: query class.
+ * @param region: where to allocate result delegation.
+ * @return new delegation or NULL on error or if not found in cache.
+ */
+struct delegpt* dns_cache_find_delegation(struct module_env* env, 
+       uint8_t* qname, size_t qnamelen, uint16_t qclass, 
+       struct region* region);
+
+/** Find cached message */
+/** Find covering DNAME */
+
+#endif /* SERVICES_CACHE_DNS_H */
index a35e14d41d79c58a6d93ce0d92e53e4ce095121a..cf87bfe7789d090465a54853a1558ed2d7a2c857 100644 (file)
@@ -174,3 +174,35 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
                return 1;
        return 0;
 }
+
+struct ub_packed_rrset_key* 
+rrset_cache_lookup(struct rrset_cache* r, uint8_t* qname, size_t qnamelen, 
+       uint16_t qtype, uint16_t qclass, uint32_t flags, uint32_t timenow,
+       int wr)
+{
+       struct lruhash_entry* e;
+       struct ub_packed_rrset_key key;
+       
+       key.entry.key = &key;
+       key.entry.data = NULL;
+       key.rk.dname = qname;
+       key.rk.dname_len = qnamelen;
+       key.rk.type = htons(qtype);
+       key.rk.rrset_class = htons(qclass);
+       key.rk.flags = flags;
+
+       key.entry.hash = rrset_key_hash(&key.rk);
+
+       if((e = slabhash_lookup(&r->table, key.entry.hash, &key, wr))) {
+               /* check TTL */
+               struct packed_rrset_data* data = 
+                       (struct packed_rrset_data*)e->data;
+               if(timenow > data->ttl) {
+                       lock_rw_unlock(e->lock);
+                       return NULL;
+               }
+               /* we're done */
+               return (struct ub_packed_rrset_key*)e->key;
+       }
+       return NULL;
+}
index 313a69452b72a73a8d358ce4697960db0b7c286f..d4630b14f23498fbde79d163d5ad965a71059ed1 100644 (file)
@@ -128,4 +128,22 @@ void rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key,
 int rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref, 
        struct alloc_cache* alloc, uint32_t timenow);
 
+/**
+ * Lookup rrset. You obtain read/write lock. You must unlock before lookup
+ * anything of else.
+ * @param r: the rrset cache.
+ * @param qname: name of rrset to lookup.
+ * @param qnamelen: length of name of rrset to lookup.
+ * @param qtype: type of rrset to lookup (host order).
+ * @param qclass: class of rrset to lookup (host order).
+ * @param flags: rrset flags, or 0.
+ * @param timenow: used to compare with TTL.
+ * @param wr: set true to get writelock.
+ * @return packed rrset key pointer. Remember to unlock the key.entry.lock.
+ *     or NULL if could not be found or it was timed out.
+ */
+struct ub_packed_rrset_key* rrset_cache_lookup(struct rrset_cache* r,
+       uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
+       uint32_t flags, uint32_t timenow, int wr);
+
 #endif /* SERVICES_CACHE_RRSET_H */
index fdb0974291d264574e815d43de9c974a13313602..25b3183853284862b3c5a294c5708ff6f3944182 100644 (file)
 
 /** number of times to retry making a random ID that is unique. */
 #define MAX_ID_RETRY 1000
-/** byte size of ip4 address */
-#define INET_SIZE 4
-/** byte size of ip6 address */
-#define INET6_SIZE 16 
 /** number of retries on outgoing UDP queries */
 #define OUTBOUND_UDP_RETRY 4
 
index 01964477d2a8e13305a1418a198d6b77a8cca54d..ebc88808a54ff06738f7618b6710e8935ad7454d 100644 (file)
@@ -160,9 +160,11 @@ static hashvalue_t
 pkt_hash_rrset(ldns_buffer* pkt, uint8_t* dname, uint16_t type, 
        uint16_t dclass, uint32_t rrset_flags)
 {
+       /* note this MUST be identical to rrset_key_hash in packed_rrset.c */
+       /* this routine handles compressed names */
        hashvalue_t h = 0xab;
-       h = hashlittle(&type, sizeof(type), h);
-       h = hashlittle(&dclass, sizeof(dclass), h);
+       h = hashlittle(&type, sizeof(type), h);         /* host order */
+       h = hashlittle(&dclass, sizeof(dclass), h);     /* netw order */
        h = hashlittle(&rrset_flags, sizeof(uint32_t), h);
        h = dname_pkt_hash(pkt, dname, h);
        return h;
index d4f3a82d00979e424926cd2488190eaf139762e3..abd9bda9469a32b1be2f75d7e31d10892026152a 100644 (file)
@@ -285,7 +285,6 @@ parse_copy_decompress(ldns_buffer* pkt, struct msg_parse* msg,
 {
        int ret;
        size_t i;
-       uint16_t t;
        struct rrset_parse *pset = msg->rrset_first;
        struct packed_rrset_data* data;
        log_assert(rep);
@@ -296,18 +295,14 @@ parse_copy_decompress(ldns_buffer* pkt, struct msg_parse* msg,
        for(i=0; i<rep->rrset_count; i++) {
                rep->rrsets[i]->rk.flags = pset->flags;
                rep->rrsets[i]->rk.dname_len = pset->dname_len;
-               rep->rrsets[i]->rk.dname = (uint8_t*)malloc(
-                       pset->dname_len + 4 /* size of type and class */ );
+               rep->rrsets[i]->rk.dname = (uint8_t*)malloc(pset->dname_len);
                if(!rep->rrsets[i]->rk.dname)
                        return LDNS_RCODE_SERVFAIL;
                /** copy & decompress dname */
                dname_pkt_copy(pkt, rep->rrsets[i]->rk.dname, pset->dname);
                /** copy over type and class */
-               t = htons(pset->type);
-               memmove(&rep->rrsets[i]->rk.dname[pset->dname_len], 
-                       &t, sizeof(uint16_t));
-               memmove(&rep->rrsets[i]->rk.dname[pset->dname_len+2], 
-                       &pset->rrset_class, sizeof(uint16_t));
+               rep->rrsets[i]->rk.type = htons(pset->type);
+               rep->rrsets[i]->rk.rrset_class = pset->rrset_class;
                /** read data part. */
                if((ret=parse_create_rrset(pkt, pset, &data)) != 0)
                        return ret;
@@ -771,14 +766,12 @@ compress_owner(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
                        /* check if typeclass+4 ttl + rdatalen is available */
                        if(ldns_buffer_remaining(pkt) < 4+4+2)
                                return RETVAL_TRUNC;
-                       ldns_buffer_write(pkt, &key->rk.dname[
-                               key->rk.dname_len], 4);
                } else {
                        /* no compress */
                        if(ldns_buffer_remaining(pkt) < key->rk.dname_len+4+4+2)
                                return RETVAL_TRUNC;
                        ldns_buffer_write(pkt, key->rk.dname, 
-                               key->rk.dname_len+4);
+                               key->rk.dname_len);
                        if(owner_pos <= PTR_MAX_OFFSET)
                                *owner_ptr = htons(PTR_CREATE(owner_pos));
                }
@@ -796,7 +789,6 @@ compress_owner(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
                                return RETVAL_TRUNC;
                        ldns_buffer_write(pkt, owner_ptr, 2);
                }
-               ldns_buffer_write(pkt, &key->rk.dname[key->rk.dname_len], 4);
        }
        return RETVAL_OK;
 }
@@ -824,9 +816,7 @@ compress_any_dname(uint8_t* dname, ldns_buffer* pkt, int labs,
 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);
+       uint16_t t = ntohs(key->rk.type);
        if(ldns_rr_descript(t) && 
                ldns_rr_descript(t)->_compress == LDNS_RR_COMPRESS)
                return ldns_rr_descript(t);
@@ -909,6 +899,8 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
                                owner_pos, &owner_ptr, owner_labs))
                                != RETVAL_OK)
                                return r;
+                       ldns_buffer_write(pkt, &key->rk.type, 2);
+                       ldns_buffer_write(pkt, &key->rk.rrset_class, 2);
                        ldns_buffer_write_u32(pkt, data->rr_ttl[i]-timenow);
                        if(c) {
                                if((r=compress_rdata(pkt, data->rr_data[i],
@@ -942,8 +934,7 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
                                        return RETVAL_TRUNC;
                        }
                        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(pkt, &key->rk.rrset_class, 2);
                        ldns_buffer_write_u32(pkt, data->rr_ttl[i]-timenow);
                        /* rrsig rdata cannot be compressed, perform 100+ byte
                         * memcopy. */
index 23aa080a27bf94d6713e39c61490aa1309423338..fb8a422849fe4c6718148bdee38de662df5b5b4f 100644 (file)
@@ -41,6 +41,8 @@
 
 #include "config.h"
 #include "util/data/packed_rrset.h"
+#include "util/data/dname.h"
+#include "util/storage/lookup3.h"
 #include "util/log.h"
 #include "util/alloc.h"
 
@@ -85,6 +87,11 @@ ub_rrset_compare(void* k1, void* k2)
        int c;
        if(key1 == key2 || key1->id == key2->id)
                return 0;
+       if(key1->rk.type != key2->rk.type) {
+               if(key1->rk.type < key2->rk.type)
+                       return -1;
+               return 1;
+       }
        if(key1->rk.dname_len != key2->rk.dname_len) {
                if(key1->rk.dname_len < key2->rk.dname_len)
                        return -1;
@@ -92,6 +99,11 @@ ub_rrset_compare(void* k1, void* k2)
        }
        if((c=memcmp(key1->rk.dname, key2->rk.dname, key1->rk.dname_len)) != 0)
                return c;
+       if(key1->rk.rrset_class != key2->rk.rrset_class) {
+               if(key1->rk.rrset_class < key2->rk.rrset_class)
+                       return -1;
+               return 1;
+       }
        if(key1->rk.flags != key2->rk.flags) {
                if(key1->rk.flags < key2->rk.flags)
                        return -1;
@@ -137,3 +149,18 @@ rrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2)
        }
        return 1;
 }
+
+hashvalue_t 
+rrset_key_hash(struct packed_rrset_key* key)
+{
+       /* type is hashed in host order */
+       uint16_t t = ntohs(key->type);
+       /* Note this MUST be identical to pkt_hash_rrset in msgparse.c */
+       /* this routine does not have a compressed name */
+       hashvalue_t h = 0xab;
+        h = hashlittle(&t, sizeof(t), h);
+        h = hashlittle(&key->rrset_class, sizeof(uint16_t), h);
+        h = hashlittle(&key->flags, sizeof(uint32_t), h);
+       h = dname_query_hash(key->dname, h);
+       return h;
+}
index 3570fafb36060d25f13111067b1a8dea008687ab..02f883d3887289cecd59b9710a479358ed30a042 100644 (file)
@@ -61,14 +61,10 @@ struct packed_rrset_key {
         * The domain name. If not null (for id=0) it is allocated, and
         * contains the wireformat domain name.
         * This dname is not canonicalized.
-        * After the dname uint16_t type and uint16_t class is stored 
-        * in wireformat.
-        * Use accessor functions to get type and class values.
         */
        uint8_t* dname;
        /** 
         * Length of the domain name, including last 0 root octet. 
-        * The value+sizeof(uint16_t)*2 is actually allocated. 
         */
        size_t dname_len;
        /**
@@ -77,6 +73,10 @@ struct packed_rrset_key {
         *      o PACKED_RRSET_CD
         */
        uint32_t flags;
+       /** the rrset type in network format */
+       uint16_t type;
+       /** the rrset class in network format */
+       uint16_t rrset_class;
 };
 
 /**
@@ -279,4 +279,11 @@ void ub_rrset_key_delete(void* key, void* userdata, int is_locked);
  */
 void rrset_data_delete(void* data, void* userdata);
 
+/**
+ * Calculate hash value for a packed rrset key.
+ * @param key: the rrset key with name, type, class, flags.
+ * @return hash value.
+ */
+hashvalue_t rrset_key_hash(struct packed_rrset_key* key);
+
 #endif /* UTIL_DATA_PACKED_RRSET_H */
index a223fa4bfc501d0d59b1ae61fc9894e3cf51adbe..85ac3b282c86a4914389ce2e5d212bac3c18c279 100644 (file)
 #define EDNS_ADVERTISED_SIZE    4096
 /** bits for EDNS bitfield */
 #define EDNS_DO 0x8000 /* Dnssec Ok */
+/** byte size of ip4 address */
+#define INET_SIZE 4
+/** byte size of ip6 address */
+#define INET6_SIZE 16
 
 /**
  * See if string is ip4 or ip6.