]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3140. [func] New command "rndc flushtree <name>" clears the
authorEvan Hunt <each@isc.org>
Tue, 2 Aug 2011 20:36:13 +0000 (20:36 +0000)
committerEvan Hunt <each@isc.org>
Tue, 2 Aug 2011 20:36:13 +0000 (20:36 +0000)
specified name from the server cache along with
all names under it. [RT #19970]

13 files changed:
CHANGES
bin/named/control.c
bin/named/include/named/control.h
bin/named/include/named/server.h
bin/named/server.c
bin/tests/system/cacheclean/ns1/named.conf
bin/tests/system/cacheclean/ns2/named.conf
bin/tests/system/cacheclean/tests.sh
doc/arm/Bv9ARM-book.xml
lib/dns/cache.c
lib/dns/include/dns/cache.h
lib/dns/include/dns/view.h
lib/dns/view.c

diff --git a/CHANGES b/CHANGES
index 17a7d17ce3a338c2f7b820b1d457dfe4f1d8cef2..7260e9581aa78bb204a9e8f25c4dde45e57e622e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+3140.  [func]          New command "rndc flushtree <name>" clears the 
+                       specified name from the server cache along with
+                       all names under it. [RT #19970]
+
 3139.  [test]          Added tests from RFC 6234, RFC 2202, and RFC 1321
                        for the hashing algorithms (md5, sha1 - sha512, and
                        their hmac counterparts).  [RT #25067] 
index e5295ca7227b65ec1ab8874f5dfc5dbd27e2e9cc..3e5de3e7b46330177e90768e08fd7824a9a44f15 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: control.c,v 1.43 2011/03/21 23:47:21 tbox Exp $ */
+/* $Id: control.c,v 1.44 2011/08/02 20:36:11 each Exp $ */
 
 /*! \file */
 
@@ -169,7 +169,9 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
        } else if (command_compare(command, NS_COMMAND_FLUSH)) {
                result = ns_server_flushcache(ns_g_server, command);
        } else if (command_compare(command, NS_COMMAND_FLUSHNAME)) {
-               result = ns_server_flushname(ns_g_server, command);
+               result = ns_server_flushnode(ns_g_server, command, ISC_FALSE);
+       } else if (command_compare(command, NS_COMMAND_FLUSHTREE)) {
+               result = ns_server_flushnode(ns_g_server, command, ISC_TRUE);
        } else if (command_compare(command, NS_COMMAND_STATUS)) {
                result = ns_server_status(ns_g_server, text);
        } else if (command_compare(command, NS_COMMAND_TSIGLIST)) {
index da680e1dcbca21434093c4ecff84bc4eb90a515f..3d451e95f7703cf22fb48bf47d9785d1b2aad55d 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: control.h,v 1.33 2011/03/21 23:47:21 tbox Exp $ */
+/* $Id: control.h,v 1.34 2011/08/02 20:36:12 each Exp $ */
 
 #ifndef NAMED_CONTROL_H
 #define NAMED_CONTROL_H 1
@@ -47,6 +47,7 @@
 #define NS_COMMAND_NOTRACE     "notrace"
 #define NS_COMMAND_FLUSH       "flush"
 #define NS_COMMAND_FLUSHNAME   "flushname"
+#define NS_COMMAND_FLUSHTREE   "flushtree"
 #define NS_COMMAND_STATUS      "status"
 #define NS_COMMAND_TSIGLIST    "tsig-list"
 #define NS_COMMAND_TSIGDELETE  "tsig-delete"
index 1346c7b9c580c81899a10ff90329723e71b77ae5..92e6d22422d075ef1bad6a05d60066687592c274 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.h,v 1.112 2011/03/21 23:47:21 tbox Exp $ */
+/* $Id: server.h,v 1.113 2011/08/02 20:36:12 each Exp $ */
 
 #ifndef NAMED_SERVER_H
 #define NAMED_SERVER_H 1
@@ -264,10 +264,12 @@ isc_result_t
 ns_server_flushcache(ns_server_t *server, char *args);
 
 /*%
- * Flush a particular name from the server's cache(s)
+ * Flush a particular name from the server's cache.  If 'tree' is false,
+ * also flush the name from the ADB and badcache.  If 'tree' is true, also
+ * flush all the names under the specified name.
  */
 isc_result_t
-ns_server_flushname(ns_server_t *server, char *args);
+ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree);
 
 /*%
  * Report the server's status.
index c9a9ac6635a4e920a463ae124c57f0777b836ae5..bef3f8c95c0f216857834f11d72377998d188eee 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.c,v 1.615 2011/07/28 03:18:17 each Exp $ */
+/* $Id: server.c,v 1.616 2011/08/02 20:36:11 each Exp $ */
 
 /*! \file */
 
@@ -6751,7 +6751,7 @@ ns_server_flushcache(ns_server_t *server, char *args) {
 }
 
 isc_result_t
-ns_server_flushname(ns_server_t *server, char *args) {
+ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree) {
        char *ptr, *target, *viewname;
        dns_view_t *view;
        isc_boolean_t flushed;
@@ -6798,13 +6798,15 @@ ns_server_flushname(ns_server_t *server, char *args) {
                 * if some of the views share a single cache.  But since the
                 * operation is lightweight we prefer simplicity here.
                 */
-               result = dns_view_flushname(view, name);
+               result = dns_view_flushnode(view, name, tree);
                if (result != ISC_R_SUCCESS) {
                        flushed = ISC_FALSE;
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
                                      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
-                                     "flushing name '%s' in cache view '%s' "
-                                     "failed: %s", target, view->name,
+                                     "flushing %s '%s' in cache view '%s' "
+                                     "failed: %s",
+                                     tree ? "tree" : "name",
+                                     target, view->name,
                                      isc_result_totext(result));
                }
        }
@@ -6812,21 +6814,26 @@ ns_server_flushname(ns_server_t *server, char *args) {
                if (viewname != NULL)
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
                                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
-                                     "flushing name '%s' in cache view '%s' "
-                                     "succeeded", target, viewname);
+                                     "flushing %s '%s' in cache view '%s' "
+                                     "succeeded",
+                                     tree ? "tree" : "name",
+                                     target, viewname);
                else
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
                                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
-                                     "flushing name '%s' in all cache views "
-                                     "succeeded", target);
+                                     "flushing %s '%s' in all cache views "
+                                     "succeeded",
+                                     tree ? "tree" : "name",
+                                     target);
                result = ISC_R_SUCCESS;
        } else {
                if (!found)
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
                                      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
-                                     "flushing name '%s' in cache view '%s' "
-                                     "failed: view not found", target,
-                                     viewname);
+                                     "flushing %s '%s' in cache view '%s' "
+                                     "failed: view not found",
+                                     tree ? "tree" : "name",
+                                     target, viewname);
                result = ISC_R_FAILURE;
        }
        isc_task_endexclusive(server->task);
index 9f341486b04301aa148d824961e647c15874dd21..9f3e37e69c84964c93fbbca43487112255f96295 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: named.conf,v 1.9 2007/06/19 23:47:01 tbox Exp $ */
+/* $Id: named.conf,v 1.10 2011/08/02 20:36:12 each Exp $ */
 
 controls { /* empty */ };
 
@@ -36,3 +36,8 @@ zone "." {
        type master;
        file "example.db";
 };
+
+zone "flushtest.example" {
+       type master;
+       file "flushtest.db";
+};
index c0d9f4417f77e9ce7ad9e91ad753f19676fb2cea..381ece7b54ba5ee6c201f3e3567b55d0f6dbea7b 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: named.conf,v 1.8 2007/06/19 23:47:01 tbox Exp $ */
+/* $Id: named.conf,v 1.9 2011/08/02 20:36:12 each Exp $ */
 
 controls { /* empty */ };
 
@@ -32,7 +32,21 @@ options {
        disable-empty-zone 127.IN-ADDR.ARPA;
 };
 
+key rndc_key {
+       secret "1234abcd8765";
+       algorithm hmac-md5;
+};
+
+controls {
+       inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
+
 zone "." {
        type hint;
        file "../../common/root.hint";
 };
+
+zone "flushtest.example" {
+       type forward;
+       forwarders { 10.53.0.1; };
+};
index 7e1ba79896968e39ee4edf3611252fc5d61f838a..61310a422715e5c59579a0437696064428368b75 100644 (file)
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: tests.sh,v 1.5 2007/06/19 23:47:00 tbox Exp $
+# $Id: tests.sh,v 1.6 2011/08/02 20:36:12 each Exp $
 
 SYSTEMTESTTOP=..
 . $SYSTEMTESTTOP/conf.sh
 
 status=0
 
-$DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat \
-       -f dig.batch -p 5300 @10.53.0.2 > dig.out.ns2 || status=1
+RNDCOPTS="-c ../common/rndc.conf -s 10.53.0.2 -p 9953"
+DIGOPTS="+nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm \
+         +nostat @10.53.0.2 -p 5300"
+
+# fill the cache with nodes from flushtest.example zone
+load_cache () {
+        # empty all existing cache data
+        $RNDC $RNDCOPTS flush
+
+       # load the positive cache entries
+       $DIG $DIGOPTS txt top1.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt second1.top1.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt third1.second1.top1.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt third2.second1.top1.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt second2.top1.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt second3.top1.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt second1.top2.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt second2.top2.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt second3.top2.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt top3.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt second1.top3.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt third1.second1.top3.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt third2.second1.top3.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt third1.second2.top3.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt third2.second2.top3.flushtest.example > /dev/null 2>1
+       $DIG $DIGOPTS txt second3.top3.flushtest.example > /dev/null 2>1
+
+       # load the negative cache entries
+        # nxrrset:
+       $DIG $DIGOPTS a third1.second1.top1.flushtest.example > /dev/null
+        # nxdomain:
+       $DIG $DIGOPTS txt top4.flushtest.example > /dev/null
+        # empty nonterminal:
+       $DIG $DIGOPTS txt second2.top3.flushtest.example > /dev/null
+
+       # sleep one second ensure the TTLs will be lower on cached data
+       sleep 1
+}
+
+dump_cache () {
+        rm -f ns2/named_dump.db
+        $RNDC $RNDCOPTS dumpdb -cache
+        sleep 1
+}
+
+clear_cache () {
+        $RNDC $RNDCOPTS flush
+}
+
+in_cache () {
+        ttl=`$DIG $DIGOPTS "$@" | awk '{print $2}'`
+        [ -z "$ttl" ] && {
+                ttl=`$DIG $DIGOPTS +noanswer +auth "$@" | awk '{print $2}'`
+                [ "$ttl" -eq 3600 ] && return 1
+                return 0
+        }
+        [ "$ttl" -eq 3600 ] && return 1
+        return 0
+}
+
+echo "I:check correctness of routine cache cleaning"
+$DIG $DIGOPTS -f dig.batch > dig.out.ns2 || status=1
 grep ";" dig.out.ns2
 
 $PERL ../digcomp.pl dig.out.ns2 knowngood.dig.out || status=1
 
+echo "I:reset and check that records are correctly cached initially"
+ret=0
+load_cache
+dump_cache
+nrecords=`grep flushtest.example ns2/named_dump.db | grep -v '^;' | wc -l`
+[ $nrecords -eq 20 ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:check flushing of the full cache"
+ret=0
+clear_cache
+dump_cache
+nrecords=`grep flushtest.example ns2/named_dump.db | grep -v '^;' | wc -l`
+[ $nrecords -eq 0 ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:check flushing of individual nodes"
+ret=0
+clear_cache
+load_cache
+# interior node
+in_cache txt top1.flushtest.example || ret=1
+$RNDC $RNDCOPTS flushname top1.flushtest.example
+in_cache txt top1.flushtest.example && ret=1
+
+# leaf node, under the interior node (should still exist)
+in_cache txt third2.second1.top1.flushtest.example || ret=1
+$RNDC $RNDCOPTS flushname third2.second1.top1.flushtest.example
+in_cache txt third2.second1.top1.flushtest.example && ret=1
+
+# another leaf node, with both positive and negative cache entries
+in_cache a third1.second1.top1.flushtest.example || ret=1
+in_cache txt third1.second1.top1.flushtest.example || ret=1
+$RNDC $RNDCOPTS flushname third1.second1.top1.flushtest.example
+in_cache a third1.second1.top1.flushtest.example && ret=1
+in_cache txt third1.second1.top1.flushtest.example && ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:check flushing of namespaces"
+ret=0
+clear_cache
+load_cache
+# flushing leaf node should leave the interior node:
+in_cache txt third1.second1.top1.flushtest.example || ret=1
+in_cache txt top1.flushtest.example || ret=1
+$RNDC $RNDCOPTS flushtree third1.second1.top1.flushtest.example
+in_cache txt third1.second1.top1.flushtest.example && ret=1
+in_cache txt top1.flushtest.example || ret=1
+in_cache txt second1.top1.flushtest.example || ret=1
+in_cache txt third2.second1.top1.flushtest.example || ret=1
+$RNDC $RNDCOPTS flushtree second1.top1.flushtest.example
+in_cache txt top1.flushtest.example || ret=1
+in_cache txt second1.top1.flushtest.example && ret=1
+in_cache txt third2.second1.top1.flushtest.example && ret=1
+
+# flushing from an empty node should still remove all its children
+in_cache txt second1.top2.flushtest.example || ret=1
+$RNDC $RNDCOPTS flushtree top2.flushtest.example
+in_cache txt second1.top2.flushtest.example && ret=1
+in_cache txt second2.top2.flushtest.example && ret=1
+in_cache txt second3.top2.flushtest.example && ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:check the number of cached records remaining"
+ret=0
+dump_cache
+nrecords=`grep flushtest.example ns2/named_dump.db | grep -v '^;' | wc -l`
+[ $nrecords -eq 19 ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
 echo "I:exit status: $status"
 exit $status
index 59b73e4f83bb453d15dc965d935ce5290ae47a05..33a1fb54c98abfb9910596788a3c053764b568bc 100644 (file)
@@ -18,7 +18,7 @@
  - PERFORMANCE OF THIS SOFTWARE.
 -->
 
-<!-- File: $Id: Bv9ARM-book.xml,v 1.498 2011/07/28 03:18:17 each Exp $ -->
+<!-- File: $Id: Bv9ARM-book.xml,v 1.499 2011/08/02 20:36:12 each Exp $ -->
 <book xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>BIND 9 Administrator Reference Manual</title>
 
@@ -1431,10 +1431,29 @@ zone "eng.example.com" {
                   </varlistentry>
 
                   <varlistentry>
-                    <term><userinput>flushname</userinput> <replaceable>name</replaceable></term>
+                    <term><userinput>flushname</userinput>
+                       <replaceable>name</replaceable>
+                       <optional><replaceable>view<replaceable></optional>
+                       </term>
                     <listitem>
                       <para>
-                        Flushes the given name from the server's cache.
+                        Flushes the given name from the server's DNS cache,
+                        and from the server's nameserver address database
+                        if applicable.
+                      </para>
+                    </listitem>
+                  </varlistentry>
+
+                  <varlistentry>
+                    <term><userinput>flushtree</userinput>
+                       <replaceable>name</replaceable>
+                       <optional><replaceable>view<replaceable></optional>
+                       </term>
+                    <listitem>
+                      <para>
+                        Flushes the given name, and all of its subdomains,
+                        from the server's DNS cache.  (The server's
+                        nameserver address database is not affected.)
                       </para>
                     </listitem>
                   </varlistentry>
index 781197551641817fc915bfda99065579255b9042..a13a4aee52e5d28edebff84e8858c86136b7c6c1 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: cache.c,v 1.89 2011/03/03 23:47:32 tbox Exp $ */
+/* $Id: cache.c,v 1.90 2011/08/02 20:36:12 each Exp $ */
 
 /*! \file */
 
@@ -1153,31 +1153,14 @@ dns_cache_flush(dns_cache_t *cache) {
        return (ISC_R_SUCCESS);
 }
 
-isc_result_t
-dns_cache_flushname(dns_cache_t *cache, dns_name_t *name) {
+static isc_result_t
+clearnode(dns_db_t *db, dns_dbnode_t *node) {
        isc_result_t result;
        dns_rdatasetiter_t *iter = NULL;
-       dns_dbnode_t *node = NULL;
-       dns_db_t *db = NULL;
-
-       LOCK(&cache->lock);
-       if (cache->db != NULL)
-               dns_db_attach(cache->db, &db);
-       UNLOCK(&cache->lock);
-       if (db == NULL)
-               return (ISC_R_SUCCESS);
-       result = dns_db_findnode(cache->db, name, ISC_FALSE, &node);
-       if (result == ISC_R_NOTFOUND) {
-               result = ISC_R_SUCCESS;
-               goto cleanup_db;
-       }
-       if (result != ISC_R_SUCCESS)
-               goto cleanup_db;
 
-       result = dns_db_allrdatasets(cache->db, node, NULL,
-                                    (isc_stdtime_t)0, &iter);
+       result = dns_db_allrdatasets(db, node, NULL, (isc_stdtime_t)0, &iter);
        if (result != ISC_R_SUCCESS)
-               goto cleanup_node;
+               return (result);
 
        for (result = dns_rdatasetiter_first(iter);
             result == ISC_R_SUCCESS;
@@ -1187,19 +1170,98 @@ dns_cache_flushname(dns_cache_t *cache, dns_name_t *name) {
                dns_rdataset_init(&rdataset);
 
                dns_rdatasetiter_current(iter, &rdataset);
-               result = dns_db_deleterdataset(cache->db, node, NULL,
+               result = dns_db_deleterdataset(db, node, NULL,
                                               rdataset.type, rdataset.covers);
                dns_rdataset_disassociate(&rdataset);
                if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
                        break;
        }
+
        if (result == ISC_R_NOMORE)
                result = ISC_R_SUCCESS;
 
        dns_rdatasetiter_destroy(&iter);
+       return (result);
+}
 
- cleanup_node:
-       dns_db_detachnode(cache->db, &node);
+static isc_result_t
+cleartree(dns_db_t *db, dns_name_t *name) {
+       isc_result_t result;
+       dns_dbiterator_t *iter = NULL;
+       dns_dbnode_t *node = NULL;
+       dns_fixedname_t fnodename;
+       dns_name_t *nodename;
+
+       dns_fixedname_init(&fnodename);
+       nodename = dns_fixedname_name(&fnodename);
+
+       result = dns_db_createiterator(db, 0, &iter);
+       if (result != ISC_R_SUCCESS)
+               goto cleanup;
+
+       result = dns_dbiterator_seek(iter, name);
+       if (result != ISC_R_SUCCESS)
+               goto cleanup;
+
+       while (result == ISC_R_SUCCESS) {
+               result = dns_dbiterator_current(iter, &node, nodename);
+               if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
+                       goto cleanup;
+               if (! dns_name_issubdomain(nodename, name))
+                       goto cleanup;
+
+               result = clearnode(db, node);
+               dns_db_detachnode(db, &node);
+               result = dns_dbiterator_next(iter);
+       }
+
+ cleanup:
+       if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
+               result = ISC_R_SUCCESS;
+       if (node != NULL)
+               dns_db_detachnode(db, &node);
+       if (iter != NULL)
+               dns_dbiterator_destroy(&iter);
+
+       return (result);
+}
+
+isc_result_t
+dns_cache_flushname(dns_cache_t *cache, dns_name_t *name) {
+       return (dns_cache_flushnode(cache, name, ISC_FALSE));
+}
+
+isc_result_t
+dns_cache_flushnode(dns_cache_t *cache, dns_name_t *name,
+                   isc_boolean_t tree)
+{
+       isc_result_t result;
+       dns_dbnode_t *node = NULL;
+       dns_db_t *db = NULL;
+
+       if (dns_name_equal(name, dns_rootname))
+               return (dns_cache_flush(cache));
+
+       LOCK(&cache->lock);
+       if (cache->db != NULL)
+               dns_db_attach(cache->db, &db);
+       UNLOCK(&cache->lock);
+       if (db == NULL)
+               return (ISC_R_SUCCESS);
+
+       if (tree) {
+               result = cleartree(cache->db, name);
+       } else {
+               result = dns_db_findnode(cache->db, name, ISC_FALSE, &node);
+               if (result == ISC_R_NOTFOUND) {
+                       result = ISC_R_SUCCESS;
+                       goto cleanup_db;
+               }
+               if (result != ISC_R_SUCCESS)
+                       goto cleanup_db;
+               result = clearnode(cache->db, node);
+               dns_db_detachnode(cache->db, &node);
+       }
 
  cleanup_db:
        dns_db_detach(&db);
index dd88760a725b4dda7aa9c624bfcd9bc6f0b06f2a..931c47b0e395607580184c586fb35ab262f397d0 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: cache.h,v 1.30 2011/03/03 23:47:32 tbox Exp $ */
+/* $Id: cache.h,v 1.31 2011/08/02 20:36:13 each Exp $ */
 
 #ifndef DNS_CACHE_H
 #define DNS_CACHE_H 1
@@ -279,10 +279,28 @@ dns_cache_flush(dns_cache_t *cache);
  *\li  #ISC_R_NOMEMORY
  */
 
+isc_result_t
+dns_cache_flushnode(dns_cache_t *cache, dns_name_t *name,
+                    isc_boolean_t tree);
+/*
+ * Flush a given name from the cache.  If 'tree' is true, then
+ * also flush all names under 'name'.
+ *
+ * Requires:
+ *\li  'cache' to be valid.
+ *\li  'name' to be valid.
+ *
+ * Returns:
+ *\li  #ISC_R_SUCCESS
+ *\li  #ISC_R_NOMEMORY
+ *\li  other error returns.
+ */
+
 isc_result_t
 dns_cache_flushname(dns_cache_t *cache, dns_name_t *name);
 /*
- * Flushes a given name from the cache.
+ * Flush a given name from the cache.  Equivalent to
+ * dns_cache_flushpartial(cache, name, ISC_FALSE).
  *
  * Requires:
  *\li  'cache' to be valid.
index f0cdc462f443bfeab99f2bfee62a0dbcfd1694b9..248835569e109def971779ba6b893fddd9409882 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.h,v 1.133 2011/02/23 03:08:11 marka Exp $ */
+/* $Id: view.h,v 1.134 2011/08/02 20:36:13 each Exp $ */
 
 #ifndef DNS_VIEW_H
 #define DNS_VIEW_H 1
@@ -839,9 +839,31 @@ dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly);
  */
 
 isc_result_t
-dns_view_flushname(dns_view_t *view, dns_name_t *);
+dns_view_flushnode(dns_view_t *view, dns_name_t *name, isc_boolean_t tree);
 /*%<
- * Flush the given name from the view's cache (and ADB).
+ * Flush the given name from the view's cache (and optionally ADB/badcache).
+ *
+ * If 'tree' is true, flush 'name' and all names below it
+ * from the cache, but do not flush ADB.
+ *
+ * If 'tree' is false, flush 'name' frmo both the cache and ADB,
+ * but do not touch any other nodes.
+ *
+ * Requires:
+ *\li  'view' is valid.
+ *\li  'name' is valid.
+ *
+ * Returns:
+ *\li  #ISC_R_SUCCESS
+ *     other returns are failures.
+ */
+
+isc_result_t
+dns_view_flushname(dns_view_t *view, dns_name_t *name);
+/*%<
+ * Flush the given name from the view's cache, ADB and badcache.
+ * Equivalent to dns_view_flushnode(view, name, ISC_FALSE).
+ *
  *
  * Requires:
  *\li  'view' is valid.
@@ -857,7 +879,6 @@ dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name);
 /*%<
  * Add the given name to the delegation only table.
  *
- *
  * Requires:
  *\li  'view' is valid.
  *\li  'name' is valid.
index d9d93dba1f1f358e6dec93263d68c472d992ffb2..e2a9b88981d78554984a0840a41f5fb9ed5768ad 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.c,v 1.180 2011/03/11 06:11:25 marka Exp $ */
+/* $Id: view.c,v 1.181 2011/08/02 20:36:12 each Exp $ */
 
 /*! \file */
 
@@ -1529,16 +1529,23 @@ dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly) {
 
 isc_result_t
 dns_view_flushname(dns_view_t *view, dns_name_t *name) {
+       return (dns_view_flushnode(view, name, ISC_FALSE));
+}
+
+isc_result_t
+dns_view_flushnode(dns_view_t *view, dns_name_t *name, isc_boolean_t tree) {
 
        REQUIRE(DNS_VIEW_VALID(view));
 
-       if (view->adb != NULL)
-               dns_adb_flushname(view->adb, name);
-       if (view->cache == NULL)
-               return (ISC_R_SUCCESS);
-       if (view->resolver != NULL)
-               dns_resolver_flushbadcache(view->resolver, name);
-       return (dns_cache_flushname(view->cache, name));
+       if (!tree) {
+               if (view->adb != NULL)
+                       dns_adb_flushname(view->adb, name);
+               if (view->cache == NULL)
+                       return (ISC_R_SUCCESS);
+               if (view->resolver != NULL)
+                       dns_resolver_flushbadcache(view->resolver, name);
+       }
+       return (dns_cache_flushnode(view->cache, name, tree));
 }
 
 isc_result_t