mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-01-31 18:59:27 -05:00
flush data from cache.
git-svn-id: file:///svn/unbound/trunk@1268 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
91138fc32a
commit
16734a0e04
8 changed files with 238 additions and 4 deletions
185
daemon/remote.c
185
daemon/remote.c
|
|
@ -59,6 +59,9 @@
|
|||
#include "util/storage/slabhash.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "validator/validator.h"
|
||||
#include "validator/val_kcache.h"
|
||||
#include "validator/val_kentry.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
|
|
@ -982,6 +985,182 @@ do_lookup(SSL* ssl, struct worker* worker, char* arg)
|
|||
free(nm);
|
||||
}
|
||||
|
||||
/** flush a type */
|
||||
static void
|
||||
do_flush_type(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
uint8_t* nm;
|
||||
int nmlabs;
|
||||
size_t nmlen;
|
||||
char* arg2;
|
||||
uint16_t t;
|
||||
if(!find_arg2(ssl, arg, &arg2))
|
||||
return;
|
||||
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
|
||||
return;
|
||||
t = ldns_get_rr_type_by_name(arg2);
|
||||
rrset_cache_remove(worker->env.rrset_cache, nm, nmlen,
|
||||
t, LDNS_RR_CLASS_IN, 0);
|
||||
|
||||
free(nm);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Local info for deletion functions
|
||||
*/
|
||||
struct del_info {
|
||||
/** worker */
|
||||
struct worker* worker;
|
||||
/** name to delete */
|
||||
uint8_t* name;
|
||||
/** length */
|
||||
size_t len;
|
||||
/** labels */
|
||||
int labs;
|
||||
/** time to invalidate to */
|
||||
uint32_t expired;
|
||||
/** number of rrsets removed */
|
||||
size_t num_rrsets;
|
||||
/** number of key entries removed */
|
||||
size_t num_keys;
|
||||
};
|
||||
|
||||
/** callback to delete rrsets in a zone */
|
||||
static void
|
||||
zone_del_rrset(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
/* entry is locked */
|
||||
struct del_info* inf = (struct del_info*)arg;
|
||||
struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)e->key;
|
||||
if(dname_subdomain_c(k->rk.dname, inf->name)) {
|
||||
struct packed_rrset_data* d =
|
||||
(struct packed_rrset_data*)e->data;
|
||||
d->ttl = inf->expired;
|
||||
inf->num_rrsets++;
|
||||
}
|
||||
}
|
||||
|
||||
/** callback to delete keys in zone */
|
||||
static void
|
||||
zone_del_kcache(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
/* entry is locked */
|
||||
struct del_info* inf = (struct del_info*)arg;
|
||||
struct key_entry_key* k = (struct key_entry_key*)e->key;
|
||||
if(dname_subdomain_c(k->name, inf->name)) {
|
||||
struct key_entry_data* d = (struct key_entry_data*)e->data;
|
||||
d->ttl = inf->expired;
|
||||
inf->num_keys++;
|
||||
}
|
||||
}
|
||||
|
||||
/** traverse a lruhash */
|
||||
static void
|
||||
lruhash_traverse(struct lruhash* h, int wr,
|
||||
void (*func)(struct lruhash_entry*, void*), void* arg)
|
||||
{
|
||||
size_t i;
|
||||
struct lruhash_entry* e;
|
||||
|
||||
lock_quick_lock(&h->lock);
|
||||
for(i=0; i<h->size; i++) {
|
||||
lock_quick_lock(&h->array[i].lock);
|
||||
for(e = h->array[i].overflow_list; e; e = e->overflow_next) {
|
||||
if(wr) {
|
||||
lock_rw_wrlock(&e->lock);
|
||||
} else {
|
||||
lock_rw_rdlock(&e->lock);
|
||||
}
|
||||
(*func)(e, arg);
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
lock_quick_unlock(&h->array[i].lock);
|
||||
}
|
||||
lock_quick_unlock(&h->lock);
|
||||
}
|
||||
|
||||
/** traverse a slabhash */
|
||||
static void
|
||||
slabhash_traverse(struct slabhash* sh, int wr,
|
||||
void (*func)(struct lruhash_entry*, void*), void* arg)
|
||||
{
|
||||
size_t i;
|
||||
for(i=0; i<sh->size; i++)
|
||||
lruhash_traverse(sh->array[i], wr, func, arg);
|
||||
}
|
||||
|
||||
/** remove all rrsets and keys from zone from cache */
|
||||
static void
|
||||
do_flush_zone(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
uint8_t* nm;
|
||||
int nmlabs;
|
||||
size_t nmlen;
|
||||
struct del_info inf;
|
||||
int idx;
|
||||
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
|
||||
return;
|
||||
/* delete all RRs and key entries from zone */
|
||||
/* what we do is to set them all expired */
|
||||
inf.worker = worker;
|
||||
inf.name = nm;
|
||||
inf.len = nmlen;
|
||||
inf.labs = nmlabs;
|
||||
inf.expired = *worker->env.now;
|
||||
inf.expired -= 3; /* handle 3 seconds skew between threads */
|
||||
inf.num_rrsets = 0;
|
||||
inf.num_keys = 0;
|
||||
slabhash_traverse(&worker->env.rrset_cache->table, 1,
|
||||
&zone_del_rrset, &inf);
|
||||
|
||||
/* and validator cache */
|
||||
idx = modstack_find(&worker->daemon->mods, "validator");
|
||||
if(idx != -1) {
|
||||
struct val_env* ve = (struct val_env*)worker->env.modinfo[idx];
|
||||
slabhash_traverse(ve->kcache->slab, 1, &zone_del_kcache, &inf);
|
||||
}
|
||||
|
||||
free(nm);
|
||||
|
||||
(void)ssl_printf(ssl, "ok removed %u rrsets and %u key entries\n",
|
||||
(unsigned)inf.num_rrsets, (unsigned)inf.num_keys);
|
||||
}
|
||||
|
||||
/** remove name rrset from cache */
|
||||
static void
|
||||
do_flush_name(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
uint8_t* nm;
|
||||
int nmlabs;
|
||||
size_t nmlen;
|
||||
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
|
||||
return;
|
||||
rrset_cache_remove(worker->env.rrset_cache, nm, nmlen,
|
||||
LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, 0);
|
||||
rrset_cache_remove(worker->env.rrset_cache, nm, nmlen,
|
||||
LDNS_RR_TYPE_AAAA, LDNS_RR_CLASS_IN, 0);
|
||||
rrset_cache_remove(worker->env.rrset_cache, nm, nmlen,
|
||||
LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN, 0);
|
||||
rrset_cache_remove(worker->env.rrset_cache, nm, nmlen,
|
||||
LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, 0);
|
||||
rrset_cache_remove(worker->env.rrset_cache, nm, nmlen,
|
||||
LDNS_RR_TYPE_CNAME, LDNS_RR_CLASS_IN, 0);
|
||||
rrset_cache_remove(worker->env.rrset_cache, nm, nmlen,
|
||||
LDNS_RR_TYPE_DNAME, LDNS_RR_CLASS_IN, 0);
|
||||
rrset_cache_remove(worker->env.rrset_cache, nm, nmlen,
|
||||
LDNS_RR_TYPE_MX, LDNS_RR_CLASS_IN, 0);
|
||||
rrset_cache_remove(worker->env.rrset_cache, nm, nmlen,
|
||||
LDNS_RR_TYPE_PTR, LDNS_RR_CLASS_IN, 0);
|
||||
rrset_cache_remove(worker->env.rrset_cache, nm, nmlen,
|
||||
LDNS_RR_TYPE_SRV, LDNS_RR_CLASS_IN, 0);
|
||||
rrset_cache_remove(worker->env.rrset_cache, nm, nmlen,
|
||||
LDNS_RR_TYPE_NAPTR, LDNS_RR_CLASS_IN, 0);
|
||||
|
||||
free(nm);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** execute a remote control command */
|
||||
static void
|
||||
execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd)
|
||||
|
|
@ -1010,6 +1189,12 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd)
|
|||
if(load_cache(ssl, rc->worker)) send_ok(ssl);
|
||||
} else if(strncmp(p, "lookup", 6) == 0) {
|
||||
do_lookup(ssl, rc->worker, skipwhite(p+6));
|
||||
} else if(strncmp(p, "flush_zone", 10) == 0) {
|
||||
do_flush_zone(ssl, rc->worker, skipwhite(p+10));
|
||||
} else if(strncmp(p, "flush_type", 10) == 0) {
|
||||
do_flush_type(ssl, rc->worker, skipwhite(p+10));
|
||||
} else if(strncmp(p, "flush", 5) == 0) {
|
||||
do_flush_name(ssl, rc->worker, skipwhite(p+5));
|
||||
} else {
|
||||
(void)ssl_printf(ssl, "error unknown command '%s'\n", p);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
23 September 2008: Wouter
|
||||
- Msg cache is loaded. A cache load enables cache responses.
|
||||
- unbound-control flush [name], flush_type and flush_zone.
|
||||
|
||||
22 September 2008: Wouter
|
||||
- dump_cache and load_cache statements in unbound-control.
|
||||
|
|
|
|||
|
|
@ -37,10 +37,10 @@ load_cache
|
|||
client sends cache contents (like from dump_cache), which is stored
|
||||
in the cache. end of data indicated with a line with 'EOF' on it.
|
||||
The data is sent after the query line.
|
||||
flush_name <name>
|
||||
flush <name>
|
||||
flushes some information regarding the name from the cache.
|
||||
removes the A, AAAA, NS, SOA, CNAME, DNAME, MX, PTR types.
|
||||
Does not remote other types.
|
||||
removes the A, AAAA, NS, SOA, CNAME, DNAME, MX, PTR, SRV, NAPTR types.
|
||||
Does not remove other types.
|
||||
flush_type <name> <RR type>
|
||||
removes rrtype entry from the cache.
|
||||
flush_zone <name>
|
||||
|
|
|
|||
2
doc/plan
2
doc/plan
|
|
@ -56,7 +56,7 @@ not stats on SIGUSR1. perhaps also see which slow auth servers cause >1sec value
|
|||
+ remote control to add/remove localinfo, redirects.
|
||||
+ remote control to load/store cache contents
|
||||
+ remote control to start, stop, reload.
|
||||
* remote control to flush names or domains (all under a name) from the
|
||||
+ remote control to flush names or domains (all under a name) from the
|
||||
cache. Include NSes. And the A, AAAA for its NSes.
|
||||
+ remote control to see delegation; what servers would be used to get
|
||||
data for a name.
|
||||
|
|
|
|||
|
|
@ -95,6 +95,22 @@ in old or wrong data returned to clients.
|
|||
.B lookup \fIname
|
||||
Print to stdout the name servers that would be used to look up the
|
||||
name specified.
|
||||
.TP
|
||||
.B flush \fIname
|
||||
Remove the name from the cache. Removes the types
|
||||
A, AAAA, NS, SOA, CNAME, DNAME, MX, PTR, SRV and NAPTR.
|
||||
Because that is fast to do. Other record types can be removed using
|
||||
.B flush_type
|
||||
or
|
||||
.B flush_zone\fR.
|
||||
.TP
|
||||
.B flush_type \fIname\fR \fItype
|
||||
Remove the name, type information from the cache.
|
||||
.TP
|
||||
.B flush_zone \fIname
|
||||
Remove all information at or below the name from the cache.
|
||||
The rrsets and key entries are removed so that new lookups will be performed.
|
||||
This needs to walk and inspect the entire cache, and is a slow operation.
|
||||
.SH "EXIT CODE"
|
||||
The unbound-control program exits with status code 1 on error, 0 on success.
|
||||
.SH "SET UP"
|
||||
|
|
|
|||
14
services/cache/rrset.c
vendored
14
services/cache/rrset.c
vendored
|
|
@ -371,3 +371,17 @@ rrset_check_sec_status(struct rrset_cache* r,
|
|||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
|
||||
void rrset_cache_remove(struct rrset_cache* r, uint8_t* nm, size_t nmlen,
|
||||
uint16_t type, uint16_t dclass, uint32_t flags)
|
||||
{
|
||||
struct ub_packed_rrset_key key;
|
||||
key.entry.key = &key;
|
||||
key.rk.dname = nm;
|
||||
key.rk.dname_len = nmlen;
|
||||
key.rk.rrset_class = htons(dclass);
|
||||
key.rk.type = htons(type);
|
||||
key.rk.flags = flags;
|
||||
key.entry.hash = rrset_key_hash(&key.rk);
|
||||
slabhash_remove(&r->table, key.entry.hash, &key);
|
||||
}
|
||||
|
|
|
|||
12
services/cache/rrset.h
vendored
12
services/cache/rrset.h
vendored
|
|
@ -209,6 +209,18 @@ void rrset_update_sec_status(struct rrset_cache* r,
|
|||
void rrset_check_sec_status(struct rrset_cache* r,
|
||||
struct ub_packed_rrset_key* rrset, uint32_t now);
|
||||
|
||||
/**
|
||||
* Remove an rrset from the cache, by name and type and flags
|
||||
* @param r: rrset cache
|
||||
* @param nm: name of rrset
|
||||
* @param nmlen: length of name
|
||||
* @param type: type of rrset
|
||||
* @param dclass: class of rrset, host order
|
||||
* @param flags: flags of rrset, host order
|
||||
*/
|
||||
void rrset_cache_remove(struct rrset_cache* r, uint8_t* nm, size_t nmlen,
|
||||
uint16_t type, uint16_t dclass, uint32_t flags);
|
||||
|
||||
/** mark rrset to be deleted, set id=0 */
|
||||
void rrset_markdel(void* key);
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,12 @@ usage()
|
|||
printf(" dump_cache print cache to stdout\n");
|
||||
printf(" load_cache load cache from stdin\n");
|
||||
printf(" lookup [name] print nameservers for name\n");
|
||||
printf(" flush [name] flushes common types for name from cache\n");
|
||||
printf(" types: A, AAAA, MX, PTR, NS,\n");
|
||||
printf(" SOA, CNAME, DNAME, SRV, NAPTR\n");
|
||||
printf(" flush_type [name] [type] flush name, type from cache\n");
|
||||
printf(" flush_zone [name] flush everything at or under name\n");
|
||||
printf(" from rr and dnssec caches\n");
|
||||
printf("Version %s\n", PACKAGE_VERSION);
|
||||
printf("BSD licensed, see LICENSE in source package for details.\n");
|
||||
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
|
||||
|
|
|
|||
Loading…
Reference in a new issue