Merge pull request #951 from NLnetLabs/cachedb-no-store

Cachedb no store
This commit is contained in:
Wouter Wijngaards 2023-10-20 17:00:13 +02:00 committed by GitHub
commit 3f66230874
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 285 additions and 2 deletions

View file

@ -815,6 +815,11 @@ cachedb_handle_response(struct module_qstate* qstate,
qstate->ext_state[id] = module_finished;
return;
}
if(qstate->env->cfg->cachedb_no_store) {
/* do not store the item in the external cache */
qstate->ext_state[id] = module_finished;
return;
}
/* store the item into the backend cache */
cachedb_extcache_store(qstate, ie);

View file

@ -1226,6 +1226,8 @@ remote-control:
# backend: "testframe"
# # secret seed string to calculate hashed keys
# secret-seed: "default"
# # if the backend should be read from, but not written to.
# cachedb-no-store: no
#
# # For "redis" backend:
# # (to enable, use --with-libhiredis to configure before compiling)

View file

@ -2681,6 +2681,11 @@ operationally.
If the backend database is shared by multiple Unbound instances,
all instances must use the same secret seed.
This option defaults to "default".
.TP
.B cachedb-no-store: \fI<yes or no>\fR
If the backend should be read from, but not written to. This makes this
instance not store dns messages in the backend. But if data is available it
is retrieved. The default is no.
.P
The following
.B cachedb

View file

@ -0,0 +1,29 @@
server:
verbosity: 4
interface: 127.0.0.1
port: @PORT@
use-syslog: no
directory: ""
pidfile: "unbound.pid"
chroot: ""
username: ""
module-config: "cachedb iterator"
do-not-query-localhost: no
qname-minimisation: no
forward-zone:
name: "."
forward-addr: 127.0.0.1@@TOPORT@
stub-zone:
name: "example.com"
stub-addr: 127.0.0.1@@TOPORT@
remote-control:
control-enable: yes
control-interface: @CONTROL_PATH@/controlpipe.@CONTROL_PID@
control-use-cert: no
cachedb:
backend: "testframe"
secret-seed: "testvalue"

View file

@ -0,0 +1,16 @@
BaseName: cachedb_no_store
Version: 1.0
Description: cachedb test the cachedb-no-store option
CreationDate: Wed 11 Oct 11:00:00 CEST 2023
Maintainer: dr. W.C.A. Wijngaards
Category:
Component:
CmdDepends:
Depends:
Help:
Pre: cachedb_no_store.pre
Post: cachedb_no_store.post
Test: cachedb_no_store.test
AuxFiles:
Passed:
Failure:

View file

@ -0,0 +1,20 @@
# #-- cachedb_no_store.post --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# source the test var file when it's there
[ -f .tpkg.var.test ] && source .tpkg.var.test
#
# do your teardown here
PRE="../.."
. ../common.sh
echo "> cat logfiles"
cat fwd.log
if test -f fwd2.log; then cat fwd2.log; else echo "no fwd2.log"; fi
if test -f fwd3.log; then cat fwd3.log; else echo "no fwd3.log"; fi
if test -f fwd4.log; then cat fwd4.log; else echo "no fwd4.log"; fi
cat unbound.log
if test -f unbound2.log; then cat unbound2.log; else echo "no unbound2.log"; fi
kill_pid $FWD_PID
kill_pid `cat unbound.pid`
rm -f $CONTROL_PATH/controlpipe.$CONTROL_PID

View file

@ -0,0 +1,36 @@
# #-- cachedb_no_store.pre--#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
PRE="../.."
. ../common.sh
if grep "define USE_CACHEDB 1" $PRE/config.h; then echo test enabled; else skip_test "test skipped"; fi
get_random_port 2
UNBOUND_PORT=$RND_PORT
FWD_PORT=$(($RND_PORT + 1))
echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test
# start forwarder
get_ldns_testns
$LDNS_TESTNS -p $FWD_PORT cachedb_no_store.testns >fwd.log 2>&1 &
FWD_PID=$!
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
# make config file
CONTROL_PATH=/tmp
CONTROL_PID=$$
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' -e 's?@CONTROL_PATH\@?'$CONTROL_PATH'?' -e 's/@CONTROL_PID@/'$CONTROL_PID'/' < cachedb_no_store.conf > ub.conf
# start unbound in the background
$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
UNBOUND_PID=$!
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
echo "CONTROL_PATH=$CONTROL_PATH" >> .tpkg.var.test
echo "CONTROL_PID=$CONTROL_PID" >> .tpkg.var.test
cat .tpkg.var.test
wait_ldns_testns_up fwd.log
wait_unbound_up unbound.log

View file

@ -0,0 +1,8 @@
ENTRY_BEGIN
MATCH opcode
ADJUST copy_id copy_query
REPLY QR AA SERVFAIL
SECTION QUESTION
txt1.example.com. IN TXT
SECTION ANSWER
ENTRY_END

View file

@ -0,0 +1,132 @@
# #-- cachedb_no_store.test --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
PRE="../.."
. ../common.sh
# do the test
get_ldns_testns
# query for a text record that is stored by unbound's cache and cachedb
# in the testframe cache.
echo "> dig txt1.example.com."
dig @localhost -p $UNBOUND_PORT txt1.example.com. TXT | tee outfile
if grep "example text message" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
# stop the forwarder with servfail, to check the answer came from the cache
echo "> stop ldns-testns"
kill_pid $FWD_PID
echo "> start ldns-testns with servfails"
$LDNS_TESTNS -p $FWD_PORT cachedb_no_store.servfail.testns >fwd2.log 2>&1 &
FWD_PID=$!
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
wait_ldns_testns_up fwd2.log
echo "> dig txt1.example.com. from unbound cache"
dig @localhost -p $UNBOUND_PORT txt1.example.com. TXT | tee outfile
if grep "example text message" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
# clear the cache of unbound, but not cachedb testframe cache
echo "> unbound-control flush"
$PRE/unbound-control -c ub.conf flush_type txt1.example.com. TXT
if test $? -ne 0; then
echo "wrong exit value."
exit 1
else
echo "exit value: OK"
fi
echo "> dig txt1.example.com. from cachedb"
dig @localhost -p $UNBOUND_PORT txt1.example.com. TXT | tee outfile
if grep "example text message" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
# start the forwarder again.
echo "> stop ldns-testns"
kill_pid $FWD_PID
echo "> start ldns-testns"
$LDNS_TESTNS -p $FWD_PORT cachedb_no_store.testns >fwd3.log 2>&1 &
FWD_PID=$!
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
wait_ldns_testns_up fwd3.log
# stop unbound to flush the cachedb cache
echo "> stop unbound"
kill_pid `cat unbound.pid`
echo ""
echo "> config unbound with cachedb-no-store: yes"
echo "cachedb: cachedb-no-store: yes" >> ub.conf
# start unbound again.
echo "> start unbound"
$PRE/unbound -d -c ub.conf >unbound2.log 2>&1 &
UNBOUND_PID=$!
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
wait_unbound_up unbound2.log
echo ""
echo "> dig txt1.example.com."
dig @localhost -p $UNBOUND_PORT txt1.example.com. TXT | tee outfile
if grep "example text message" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
# stop the forwarder with servfail, to check the answer came from the cache
echo "> stop ldns-testns"
kill_pid $FWD_PID
echo "> start ldns-testns with servfails"
$LDNS_TESTNS -p $FWD_PORT cachedb_no_store.servfail.testns >fwd4.log 2>&1 &
FWD_PID=$!
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
wait_ldns_testns_up fwd4.log
echo "> dig txt1.example.com. from unbound cache"
dig @localhost -p $UNBOUND_PORT txt1.example.com. TXT | tee outfile
if grep "example text message" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
# clear the cache of unbound, but not cachedb testframe cache
echo "> unbound-control flush"
$PRE/unbound-control -c ub.conf flush_type txt1.example.com. TXT
if test $? -ne 0; then
echo "wrong exit value."
exit 1
else
echo "exit value: OK"
fi
echo "> dig txt1.example.com. from cachedb, but that has no message stored"
dig @localhost -p $UNBOUND_PORT txt1.example.com. TXT | tee outfile
if grep "SERVFAIL" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
exit 0

View file

@ -0,0 +1,9 @@
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
txt1.example.com. IN TXT
SECTION ANSWER
txt1.example.com. IN TXT "example text message"
ENTRY_END

View file

@ -382,6 +382,7 @@ config_create(void)
#ifdef USE_CACHEDB
if(!(cfg->cachedb_backend = strdup("testframe"))) goto error_exit;
if(!(cfg->cachedb_secret = strdup("default"))) goto error_exit;
cfg->cachedb_no_store = 0;
#ifdef USE_REDIS
if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit;
cfg->redis_server_path = NULL;
@ -822,6 +823,9 @@ int config_set_option(struct config_file* cfg, const char* opt,
{ IS_NUMBER_OR_ZERO; cfg->ipsecmod_max_ttl = atoi(val); }
else S_YNO("ipsecmod-strict:", ipsecmod_strict)
#endif
#ifdef USE_CACHEDB
else S_YNO("cachedb-no-store:", cachedb_no_store)
#endif /* USE_CACHEDB */
else if(strcmp(opt, "define-tag:") ==0) {
return config_add_tag(cfg, val);
/* val_sig_skew_min, max and val_max_restart are copied into val_env
@ -1310,6 +1314,7 @@ config_get_option(struct config_file* cfg, const char* opt,
#ifdef USE_CACHEDB
else O_STR(opt, "backend", cachedb_backend)
else O_STR(opt, "secret-seed", cachedb_secret)
else O_YNO(opt, "cachedb-no-store", cachedb_no_store)
#ifdef USE_REDIS
else O_STR(opt, "redis-server-host", redis_server_host)
else O_DEC(opt, "redis-server-port", redis_server_port)

View file

@ -701,6 +701,8 @@ struct config_file {
char* cachedb_backend;
/** secret seed for hash key calculation */
char* cachedb_secret;
/** cachedb that does not store, but only reads from database, if on */
int cachedb_no_store;
#ifdef USE_REDIS
/** redis server's IP address or host name */
char* redis_server_host;

View file

@ -558,6 +558,7 @@ ipsecmod-strict{COLON} { YDVAR(1, VAR_IPSECMOD_STRICT) }
cachedb{COLON} { YDVAR(0, VAR_CACHEDB) }
backend{COLON} { YDVAR(1, VAR_CACHEDB_BACKEND) }
secret-seed{COLON} { YDVAR(1, VAR_CACHEDB_SECRETSEED) }
cachedb-no-store{COLON} { YDVAR(1, VAR_CACHEDB_NO_STORE) }
redis-server-host{COLON} { YDVAR(1, VAR_CACHEDB_REDISHOST) }
redis-server-port{COLON} { YDVAR(1, VAR_CACHEDB_REDISPORT) }
redis-server-path{COLON} { YDVAR(1, VAR_CACHEDB_REDISPATH) }

View file

@ -199,7 +199,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_INTERFACE_ACTION VAR_INTERFACE_VIEW VAR_INTERFACE_TAG
%token VAR_INTERFACE_TAG_ACTION VAR_INTERFACE_TAG_DATA
%token VAR_PROXY_PROTOCOL_PORT VAR_STATISTICS_INHIBIT_ZERO
%token VAR_HARDEN_UNKNOWN_ADDITIONAL VAR_DISABLE_EDNS_DO
%token VAR_HARDEN_UNKNOWN_ADDITIONAL VAR_DISABLE_EDNS_DO VAR_CACHEDB_NO_STORE
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@ -3712,7 +3712,7 @@ contents_cachedb: contents_cachedb content_cachedb
content_cachedb: cachedb_backend_name | cachedb_secret_seed |
redis_server_host | redis_server_port | redis_timeout |
redis_expire_records | redis_server_path | redis_server_password |
redis_logical_db
cachedb_no_store | redis_logical_db
;
cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG
{
@ -3738,6 +3738,19 @@ cachedb_secret_seed: VAR_CACHEDB_SECRETSEED STRING_ARG
#endif
}
;
cachedb_no_store: VAR_CACHEDB_NO_STORE STRING_ARG
{
#ifdef USE_CACHEDB
OUTYY(("P(cachedb_no_store:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->cachedb_no_store = (strcmp($2, "yes")==0);
#else
OUTYY(("P(Compiled without cachedb, ignoring)\n"));
#endif
free($2);
}
;
redis_server_host: VAR_CACHEDB_REDISHOST STRING_ARG
{
#if defined(USE_CACHEDB) && defined(USE_REDIS)