]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] "rndc flushtree -all <name>"
authorEvan Hunt <each@isc.org>
Wed, 26 Jun 2013 21:59:32 +0000 (14:59 -0700)
committerEvan Hunt <each@isc.org>
Wed, 26 Jun 2013 21:59:32 +0000 (14:59 -0700)
3606. [func] "rndc flushtree -all" flushes matching
records in the ADB and bad cache as well as
the DNS cache.  (Without the "-all" option,
flushtree will still only flush records from
the DNS cache.) [RT #33970]

CHANGES
bin/named/server.c
bin/rndc/rndc.docbook
bin/tests/system/cacheclean/tests.sh
lib/dns/adb.c
lib/dns/include/dns/adb.h
lib/dns/include/dns/resolver.h
lib/dns/include/dns/view.h
lib/dns/resolver.c
lib/dns/view.c
lib/dns/win32/libdns.def

diff --git a/CHANGES b/CHANGES
index fc06e5fc76f81acc912115802811d74dba659134..b15040609c1565d53d4c78f395b7981f998f6ae4 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+3606.  [func]          "rndc flushtree -all" flushes matching
+                       records in the ADB and bad cache as well as
+                       the DNS cache.  (Without the "-all" option,
+                       flushtree will still only flush records from
+                       the DNS cache.) [RT #33970]
+
 3605.  [port]          win32: Addressed several compatibility issues
                        with newer versions of Visual Studio. [RT #33916]
 
index 9f69c45a3cbf5ef97a5c6a821f73a0c7f900c7a9..fb1e22f142e024d61005a0383908d0be4095a506 100644 (file)
@@ -7614,22 +7614,27 @@ ns_server_flushcache(ns_server_t *server, char *args) {
 
 isc_result_t
 ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree) {
-       char *ptr, *target, *viewname;
+       char *target, *viewname;
        dns_view_t *view;
        isc_boolean_t flushed;
-       isc_boolean_t found;
+       isc_boolean_t found, all = ISC_FALSE;
        isc_result_t result;
        isc_buffer_t b;
        dns_fixedname_t fixed;
        dns_name_t *name;
 
        /* Skip the command name. */
-       ptr = next_token(&args, " \t");
-       if (ptr == NULL)
+       target = next_token(&args, " \t");
+       if (target == NULL)
                return (ISC_R_UNEXPECTEDEND);
 
-       /* Find the domain name to flush. */
        target = next_token(&args, " \t");
+       if (strcmp(target, "-all") == 0) {
+               all = ISC_TRUE;
+               target = next_token(&args, " \t");
+       }
+
+       /* Find the domain name to flush. */
        if (target == NULL)
                return (ISC_R_UNEXPECTEDEND);
 
@@ -7660,7 +7665,7 @@ ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree) {
                 * if some of the views share a single cache.  But since the
                 * operation is lightweight we prefer simplicity here.
                 */
-               result = dns_view_flushnode(view, name, tree);
+               result = dns_view_flushnode(view, name, tree, all);
                if (result != ISC_R_SUCCESS) {
                        flushed = ISC_FALSE;
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
index 17a4d7250d2e0eab40fd4bca7eab0150ff5821f4..472a62f8ed9e773e5a22e64501a1d7df15e5cba6 100644 (file)
       </varlistentry>
 
       <varlistentry>
-        <term><userinput>flushtree</userinput> <replaceable>name</replaceable> <optional><replaceable>view</replaceable></optional> </term>
+        <term><userinput>flushtree</userinput> <optional>-all</optional> <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.  Note that this does
-            <emphasis>not</emphasis> affect he server's address
-            database or bad-server cache.
+            from the server's DNS cache.  By default, this does
+            <emphasis>not</emphasis> affect the server's address
+            database or bad-server cache.  To eliminate matching
+            names from those databases as well, use
+            the <option>-all</option> option.  
           </para>
         </listitem>
       </varlistentry>
index 712d2b22acf2dd94ff1665b096391dd812fbe247..86e318cc4e6014c3d338edf95800e29d0593674e 100644 (file)
@@ -65,7 +65,7 @@ EOF
 
 dump_cache () {
         rm -f ns2/named_dump.db
-        $RNDC $RNDCOPTS dumpdb -cache
+        $RNDC $RNDCOPTS dumpdb -cache _default
         sleep 1
 }
 
@@ -185,5 +185,16 @@ nrecords=`grep flushtest.example ns2/named_dump.db | grep -v '^;' | grep -Ew '(T
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+echo "I:check flushtree -all clears adb correctly"
+ret=0
+load_cache
+dump_cache
+awk '/Address database/ {getline; getline; if ($2 == "ns.flushtest.example") exit(0); exit(1); }' ns2/named_dump.db || ret=1
+$RNDC $RNDCOPTS flushtree -all flushtest.example || ret=1
+dump_cache
+awk '/Address database/ {getline; getline; if ($2 == "ns.flushtest.example") exit(1); exit(0); }' ns2/named_dump.db || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
 echo "I:exit status: $status"
 exit $status
index 455bac68b483e77c793764a5ea135a542cbccfbb..a69f2537fda298a8647c52e3cee408f1961c213b 100644 (file)
@@ -4362,7 +4362,8 @@ dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) {
        dns_adbname_t *nextname;
        int bucket;
 
-       INSIST(DNS_ADB_VALID(adb));
+       REQUIRE(DNS_ADB_VALID(adb));
+       REQUIRE(name != NULL);
 
        LOCK(&adb->lock);
        bucket = dns_name_hash(name, ISC_FALSE) % adb->nnames;
@@ -4382,6 +4383,35 @@ dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) {
        UNLOCK(&adb->lock);
 }
 
+void
+dns_adb_flushnames(dns_adb_t *adb, dns_name_t *name) {
+       dns_adbname_t *adbname, *nextname;
+       unsigned int i;
+
+       REQUIRE(DNS_ADB_VALID(adb));
+       REQUIRE(name != NULL);
+
+       LOCK(&adb->lock);
+       for (i = 0; i < adb->nnames; i++) {
+               LOCK(&adb->namelocks[i]);
+               adbname = ISC_LIST_HEAD(adb->names[i]);
+               while (adbname != NULL) {
+                       isc_boolean_t ret;
+                       nextname = ISC_LIST_NEXT(adbname, plink);
+                       if (!NAME_DEAD(adbname) &&
+                           dns_name_issubdomain(&adbname->name, name))
+                       {
+                               ret = kill_name(&adbname,
+                                               DNS_EVENT_ADBCANCELED);
+                               RUNTIME_CHECK(ret == ISC_FALSE);
+                       }
+                       adbname = nextname;
+               }
+               UNLOCK(&adb->namelocks[i]);
+       }
+       UNLOCK(&adb->lock);
+}
+
 static void
 water(void *arg, int mark) {
        /*
index 27ad144311f3e733b8a8bff7334395614f3503ab..0d4891a0437d1905fa995934f45c62321b471f52 100644 (file)
@@ -718,6 +718,17 @@ dns_adb_flushname(dns_adb_t *adb, dns_name_t *name);
  *\li  'name' is valid.
  */
 
+void
+dns_adb_flushnames(dns_adb_t *adb, dns_name_t *name);
+/*%<
+ * Flush 'name' and all subdomains from the adb cache.
+ *
+ * Requires:
+ *\li  'adb' is valid.
+ *\li  'name' is valid.
+ */
+
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_ADB_H */
index 2451f9c0760f7f70d4911f932461156051c79c37..075fa8acb8aa5496bd406d816f2590cceba6fd29 100644 (file)
@@ -589,6 +589,16 @@ dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name);
  * \li resolver to be valid.
  */
 
+void
+dns_resolver_flushbadnames(dns_resolver_t *resolver, dns_name_t *name);
+/*%<
+ * Flush the bad cache of all entries at or below 'name'.
+ *
+ * Requires:
+ * \li resolver to be valid.
+ * \li  name != NULL
+ */
+
 void
 dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp);
 /*%
index 637cf433e13305fc00b5c59ef5af9ac7ad47f018..3e9e2d6640b302ec6d38a5b5ca9d2c3c738becb7 100644 (file)
@@ -875,15 +875,18 @@ dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly);
  */
 
 isc_result_t
-dns_view_flushnode(dns_view_t *view, dns_name_t *name, isc_boolean_t tree);
+dns_view_flushnode(dns_view_t *view, dns_name_t *name,
+                  isc_boolean_t cachetree, isc_boolean_t all);
 /*%<
  * 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 'cachetree' or 'all' is true, flush 'name' and all names below it
+ * from the cache.
+ * If 'all' is true, flush 'name' and all names below it from the ADB
+ * and badcache.
  *
- * If 'tree' is false, flush 'name' frmo both the cache and ADB,
- * but do not touch any other nodes.
+ * If 'cachetree' and 'all' are false, flush 'name' from both the
+ * cache and ADB, but do not touch any other nodes.
  *
  * Requires:
  *\li  'view' is valid.
index 605df695f371b4fd9595547151d4392fa319076b..13139ab084609eee39bf5de48261539caaa79a25 100644 (file)
@@ -8747,6 +8747,40 @@ dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name) {
 
 }
 
+void
+dns_resolver_flushbadnames(dns_resolver_t *resolver, dns_name_t *name) {
+       dns_badcache_t *bad, *prev, *next;
+       unsigned int i;
+
+       REQUIRE(VALID_RESOLVER(resolver));
+       REQUIRE(name != NULL);
+
+       LOCK(&resolver->lock);
+       if (resolver->badcache == NULL)
+               goto unlock;
+
+       for (i = 0; i < resolver->badhash; i++) {
+               prev = NULL;
+               for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
+                       next = bad->next;
+                       if (dns_name_issubdomain(&bad->name, name)) {
+                               if (prev == NULL)
+                                       resolver->badcache[i] = bad->next;
+                               else
+                                       prev->next = bad->next;
+                               isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
+                                           bad->name.length);
+                               resolver->badcount--;
+                       } else
+                               prev = bad;
+               }
+       }
+
+ unlock:
+       UNLOCK(&resolver->lock);
+
+}
+
 static void
 resizehash(dns_resolver_t *resolver, isc_time_t *now, isc_boolean_t grow) {
        unsigned int newsize;
index 59a5d2714e1943e0c3c13688364e53836571368a..45480c8f920c2829d5679e3ba42d43faac53f324 100644 (file)
@@ -1556,15 +1556,22 @@ 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));
+       return (dns_view_flushnode(view, name, ISC_FALSE, ISC_FALSE));
 }
 
 isc_result_t
-dns_view_flushnode(dns_view_t *view, dns_name_t *name, isc_boolean_t tree) {
+dns_view_flushnode(dns_view_t *view, dns_name_t *name,
+                  isc_boolean_t cachetree, isc_boolean_t all)
+{
 
        REQUIRE(DNS_VIEW_VALID(view));
 
-       if (!tree) {
+       if (all) {
+               if (view->adb != NULL)
+                       dns_adb_flushnames(view->adb, name);
+               if (view->resolver != NULL)
+                       dns_resolver_flushbadnames(view->resolver, name);
+       } else if (!cachetree) {
                if (view->adb != NULL)
                        dns_adb_flushname(view->adb, name);
                if (view->cache == NULL)
@@ -1572,7 +1579,8 @@ dns_view_flushnode(dns_view_t *view, dns_name_t *name, isc_boolean_t tree) {
                if (view->resolver != NULL)
                        dns_resolver_flushbadcache(view->resolver, name);
        }
-       return (dns_cache_flushnode(view->cache, name, tree));
+
+       return (dns_cache_flushnode(view->cache, name, cachetree || all));
 }
 
 isc_result_t
index 5409435c28775e32e6a9d79a76051a2916233f94..e901a61fa3e7cae47d29cab86bac7c4a238c8d38 100644 (file)
@@ -43,6 +43,8 @@ dns_adb_dump
 dns_adb_dumpfind
 dns_adb_findaddrinfo
 dns_adb_flush
+dns_adb_flushmatch
+dns_adb_flushname
 dns_adb_freeaddrinfo
 dns_adb_marklame
 dns_adb_setadbsize