/**
* Hash the query name, type, class and dbacess-secret into lookup buffer.
- * @param qstate: query state with query info
- * and env->cfg with secret.
+ * @param qinfo: query info
+ * @param env: with env->cfg with secret.
* @param buf: returned buffer with hash to lookup
* @param len: length of the buffer.
*/
static void
-calc_hash(struct module_qstate* qstate, char* buf, size_t len)
+calc_hash(struct query_info* qinfo, struct module_env* env, char* buf,
+ size_t len)
{
uint8_t clear[1024];
size_t clen = 0;
uint8_t hash[CACHEDB_HASHSIZE/8];
const char* hex = "0123456789ABCDEF";
- const char* secret = qstate->env->cfg->cachedb_secret;
+ const char* secret = env->cfg->cachedb_secret;
size_t i;
/* copy the hash info into the clear buffer */
- if(clen + qstate->qinfo.qname_len < sizeof(clear)) {
- memmove(clear+clen, qstate->qinfo.qname,
- qstate->qinfo.qname_len);
- clen += qstate->qinfo.qname_len;
+ if(clen + qinfo->qname_len < sizeof(clear)) {
+ memmove(clear+clen, qinfo->qname, qinfo->qname_len);
+ clen += qinfo->qname_len;
}
if(clen + 4 < sizeof(clear)) {
- uint16_t t = htons(qstate->qinfo.qtype);
- uint16_t c = htons(qstate->qinfo.qclass);
+ uint16_t t = htons(qinfo->qtype);
+ uint16_t c = htons(qinfo->qclass);
memmove(clear+clen, &t, 2);
memmove(clear+clen+2, &c, 2);
clen += 4;
int* msg_expired)
{
char key[(CACHEDB_HASHSIZE/8)*2+1];
- calc_hash(qstate, key, sizeof(key));
+ calc_hash(&qstate->qinfo, qstate->env, key, sizeof(key));
/* call backend to fetch data for key into scratch buffer */
if( !(*ie->backend->lookup)(qstate->env, ie, key,
cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
{
char key[(CACHEDB_HASHSIZE/8)*2+1];
- calc_hash(qstate, key, sizeof(key));
+ calc_hash(&qstate->qinfo, qstate->env, key, sizeof(key));
/* prepare data in scratch buffer */
if(!prep_data(qstate, qstate->env->scratch_buffer))
}
void cachedb_msg_remove(struct module_qstate* qstate)
+{
+ cachedb_msg_remove_qinfo(qstate->env, &qstate->qinfo);
+}
+
+void cachedb_msg_remove_qinfo(struct module_env* env, struct query_info* qinfo)
{
char key[(CACHEDB_HASHSIZE/8)*2+1];
- int id = modstack_find(qstate->env->modstack, "cachedb");
- struct cachedb_env* ie = (struct cachedb_env*)qstate->env->modinfo[id];
+ int id = modstack_find(env->modstack, "cachedb");
+ struct cachedb_env* ie = (struct cachedb_env*)env->modinfo[id];
- log_query_info(VERB_ALGO, "cachedb msg remove", &qstate->qinfo);
- calc_hash(qstate, key, sizeof(key));
- sldns_buffer_clear(qstate->env->scratch_buffer);
- sldns_buffer_write_u32(qstate->env->scratch_buffer, 0);
- sldns_buffer_flip(qstate->env->scratch_buffer);
+ log_query_info(VERB_ALGO, "cachedb msg remove", qinfo);
+ calc_hash(qinfo, env, key, sizeof(key));
+ sldns_buffer_clear(env->scratch_buffer);
+ sldns_buffer_write_u32(env->scratch_buffer, 0);
+ sldns_buffer_flip(env->scratch_buffer);
/* call backend */
- (*ie->backend->store)(qstate->env, ie, key,
- sldns_buffer_begin(qstate->env->scratch_buffer),
- sldns_buffer_limit(qstate->env->scratch_buffer),
+ (*ie->backend->store)(env, ie, key,
+ sldns_buffer_begin(env->scratch_buffer),
+ sldns_buffer_limit(env->scratch_buffer),
0);
}
#endif /* USE_CACHEDB */
#include "sldns/wire2str.h"
#include "sldns/sbuffer.h"
#include "util/timeval_func.h"
+#ifdef USE_CACHEDB
+#include "cachedb/cachedb.h"
+#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
/** flush something from rrset and msg caches */
static void
do_cache_remove(struct worker* worker, uint8_t* nm, size_t nmlen,
- uint16_t t, uint16_t c)
+ uint16_t t, uint16_t c, int remcachedb)
{
hashvalue_type h;
struct query_info k;
h = query_info_hash(&k, BIT_CD);
slabhash_remove(worker->env.msg_cache, h, &k);
}
+#ifdef USE_CACHEDB
+ if(remcachedb && worker->env.cachedb_enabled)
+ cachedb_msg_remove_qinfo(&worker->env, &k);
+#endif
+}
+
+/** parse '+c' option, modifies string to return remainder. */
+static int
+parse_remcachedb(RES* ssl, char** arg, int* pc)
+{
+ *arg = skipwhite(*arg);
+ if((*arg)[0] == '+' && (*arg)[1] == 'c') {
+ char* arg2;
+ *pc = 1;
+ if(!find_arg2(ssl, *arg, &arg2))
+ return 0;
+ *arg = arg2;
+ return 1;
+ }
+ /* The option was not found, no problem */
+ return 1;
}
/** flush a type */
size_t nmlen;
char* arg2;
uint16_t t;
+ int pc = 0; /* '+c' option */
+ if(!parse_remcachedb(ssl, &arg, &pc))
+ return;
if(!find_arg2(ssl, arg, &arg2))
return;
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
return;
t = sldns_get_rr_type_by_name(arg2);
if(t == 0 && strcmp(arg2, "TYPE0") != 0) {
+ (void)ssl_printf(ssl, "error parsing RRset type: '%s'\n", arg2);
+ free(nm);
return;
}
- do_cache_remove(worker, nm, nmlen, t, LDNS_RR_CLASS_IN);
+ do_cache_remove(worker, nm, nmlen, t, LDNS_RR_CLASS_IN, pc);
free(nm);
send_ok(ssl);
socklen_t addrlen;
/** socket address for host deletion */
struct sockaddr_storage addr;
+ /** if cachedb information should be flushed too */
+ int remcachedb;
};
/** callback to delete hosts in infra cache */
inf.num_msgs = 0;
inf.num_keys = 0;
inf.addrlen = len;
+ inf.remcachedb = 0;
memmove(&inf.addr, &addr, len);
slabhash_traverse(worker->env.infra_cache->hosts, 1, &infra_del_host,
&inf);
d->serve_expired_ttl = inf->expired;
inf->num_msgs++;
}
+#ifdef USE_CACHEDB
+ if(inf->remcachedb && inf->worker->env.cachedb_enabled)
+ cachedb_msg_remove_qinfo(&inf->worker->env, &k->key);
+#endif
}
}
int nmlabs;
size_t nmlen;
struct del_info inf;
+ int pc = 0; /* '+c' option */
+ if(!parse_remcachedb(ssl, &arg, &pc))
+ return;
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
return;
/* delete all RRs and key entries from zone */
inf.num_rrsets = 0;
inf.num_msgs = 0;
inf.num_keys = 0;
+ inf.remcachedb = pc;
slabhash_traverse(&worker->env.rrset_cache->table, 1,
&zone_del_rrset, &inf);
if(d->security == sec_status_bogus) {
d->ttl = inf->expired;
inf->num_msgs++;
+#ifdef USE_CACHEDB
+ if(inf->remcachedb && inf->worker->env.cachedb_enabled)
+ cachedb_msg_remove_qinfo(&inf->worker->env,
+ &((struct msgreply_entry*)e->key)->key);
+#endif
}
}
/** remove all bogus rrsets, msgs and keys from cache */
static void
-do_flush_bogus(RES* ssl, struct worker* worker)
+do_flush_bogus(RES* ssl, struct worker* worker, char* arg)
{
struct del_info inf;
+ int pc = 0; /* '+c' option */
+ if(!parse_remcachedb(ssl, &arg, &pc))
+ return;
/* what we do is to set them all expired */
inf.worker = worker;
inf.expired = *worker->env.now;
inf.num_rrsets = 0;
inf.num_msgs = 0;
inf.num_keys = 0;
+ inf.remcachedb = pc;
slabhash_traverse(&worker->env.rrset_cache->table, 1,
&bogus_del_rrset, &inf);
if(FLAGS_GET_RCODE(d->flags) != 0 || d->an_numrrsets == 0) {
d->ttl = inf->expired;
inf->num_msgs++;
+#ifdef USE_CACHEDB
+ if(inf->remcachedb && inf->worker->env.cachedb_enabled)
+ cachedb_msg_remove_qinfo(&inf->worker->env,
+ &((struct msgreply_entry*)e->key)->key);
+#endif
}
}
/** remove all negative(NODATA,NXDOMAIN), and servfail messages from cache */
static void
-do_flush_negative(RES* ssl, struct worker* worker)
+do_flush_negative(RES* ssl, struct worker* worker, char* arg)
{
struct del_info inf;
+ int pc = 0; /* '+c' option */
+ if(!parse_remcachedb(ssl, &arg, &pc))
+ return;
/* what we do is to set them all expired */
inf.worker = worker;
inf.expired = *worker->env.now;
inf.num_rrsets = 0;
inf.num_msgs = 0;
inf.num_keys = 0;
+ inf.remcachedb = pc;
slabhash_traverse(&worker->env.rrset_cache->table, 1,
&negative_del_rrset, &inf);
uint8_t* nm;
int nmlabs;
size_t nmlen;
+ int pc = 0; /* '+c' option */
+ if(!parse_remcachedb(ssl, &arg, &pc))
+ return;
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
return;
- do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN);
- do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_AAAA, LDNS_RR_CLASS_IN);
- do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN);
- do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN);
- do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_CNAME, LDNS_RR_CLASS_IN);
- do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_DNAME, LDNS_RR_CLASS_IN);
- do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_MX, LDNS_RR_CLASS_IN);
- do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_PTR, LDNS_RR_CLASS_IN);
- do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SRV, LDNS_RR_CLASS_IN);
- do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_NAPTR, LDNS_RR_CLASS_IN);
- do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SVCB, LDNS_RR_CLASS_IN);
- do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_HTTPS, LDNS_RR_CLASS_IN);
+ do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, pc);
+ do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_AAAA, LDNS_RR_CLASS_IN, pc);
+ do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN, pc);
+ do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, pc);
+ do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_CNAME, LDNS_RR_CLASS_IN, pc);
+ do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_DNAME, LDNS_RR_CLASS_IN, pc);
+ do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_MX, LDNS_RR_CLASS_IN, pc);
+ do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_PTR, LDNS_RR_CLASS_IN, pc);
+ do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SRV, LDNS_RR_CLASS_IN, pc);
+ do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_NAPTR, LDNS_RR_CLASS_IN, pc);
+ do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SVCB, LDNS_RR_CLASS_IN, pc);
+ do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_HTTPS, LDNS_RR_CLASS_IN, pc);
free(nm);
send_ok(ssl);
} else if(cmdcmp(p, "get_option", 10)) {
do_get_option(ssl, worker, skipwhite(p+10));
} else if(cmdcmp(p, "flush_bogus", 11)) {
- do_flush_bogus(ssl, worker);
+ do_flush_bogus(ssl, worker, skipwhite(p+11));
} else if(cmdcmp(p, "flush_negative", 14)) {
- do_flush_negative(ssl, worker);
+ do_flush_negative(ssl, worker, skipwhite(p+14));
} else if(cmdcmp(p, "rpz_enable", 10)) {
do_rpz_enable(ssl, worker, skipwhite(p+10));
} else if(cmdcmp(p, "rpz_disable", 11)) {