+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]
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);
* 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,
</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>
dump_cache () {
rm -f ns2/named_dump.db
- $RNDC $RNDCOPTS dumpdb -cache
+ $RNDC $RNDCOPTS dumpdb -cache _default
sleep 1
}
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
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;
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) {
/*
*\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 */
* \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);
/*%
*/
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.
}
+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;
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)
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
dns_adb_dumpfind
dns_adb_findaddrinfo
dns_adb_flush
+dns_adb_flushmatch
+dns_adb_flushname
dns_adb_freeaddrinfo
dns_adb_marklame
dns_adb_setadbsize