mirror of
https://github.com/NLnetLabs/unbound.git
synced 2024-09-21 06:37:08 +00:00
- Implement cachedb-check-when-serve-expired: yes option, default
is enabled. When serve expired is enabled with cachedb, it first checks cachedb before serving the expired response.
This commit is contained in:
parent
a30221c5bb
commit
d98c7b9ae3
@ -50,6 +50,8 @@
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/msgencode.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/mesh.h"
|
||||
#include "services/modstack.h"
|
||||
#include "validator/val_neg.h"
|
||||
#include "validator/val_secalgo.h"
|
||||
#include "iterator/iter_utils.h"
|
||||
@ -791,6 +793,13 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
return;
|
||||
}
|
||||
|
||||
if(qstate->serve_expired_data &&
|
||||
qstate->env->cfg->cachedb_check_when_serve_expired) {
|
||||
/* Reply with expired data if any to client, because cachedb
|
||||
* also has no useful, current data */
|
||||
mesh_respond_serve_expired(qstate->mesh_info);
|
||||
}
|
||||
|
||||
/* no cache fetches */
|
||||
/* pass request to next module */
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
@ -923,4 +932,17 @@ cachedb_get_funcblock(void)
|
||||
{
|
||||
return &cachedb_block;
|
||||
}
|
||||
|
||||
int
|
||||
cachedb_is_enabled(struct module_stack* mods, struct module_env* env)
|
||||
{
|
||||
struct cachedb_env* ie;
|
||||
int id = modstack_find(mods, "cachedb");
|
||||
if(id == -1)
|
||||
return 0;
|
||||
ie = (struct cachedb_env*)env->modinfo[id];
|
||||
if(ie && ie->enabled)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
#endif /* USE_CACHEDB */
|
||||
|
@ -41,6 +41,7 @@
|
||||
*/
|
||||
#include "util/module.h"
|
||||
struct cachedb_backend;
|
||||
struct module_stack;
|
||||
|
||||
/**
|
||||
* The global variable environment contents for the cachedb
|
||||
@ -110,3 +111,10 @@ size_t cachedb_get_mem(struct module_env* env, int id);
|
||||
*/
|
||||
struct module_func_block* cachedb_get_funcblock(void);
|
||||
|
||||
/**
|
||||
* See if the cachedb is enabled.
|
||||
* @param mods: module stack. It finds the cachedb module environment.
|
||||
* @param env: module environment.
|
||||
* @return true if exists and enabled.
|
||||
*/
|
||||
int cachedb_is_enabled(struct module_stack* mods, struct module_env* env);
|
||||
|
@ -99,6 +99,9 @@
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
#include "cachedb/cachedb.h"
|
||||
#endif
|
||||
|
||||
/** How many quit requests happened. */
|
||||
static int sig_record_quit = 0;
|
||||
@ -738,6 +741,10 @@ daemon_fork(struct daemon* daemon)
|
||||
if(!edns_strings_apply_cfg(daemon->env->edns_strings, daemon->cfg))
|
||||
fatal_exit("Could not set up EDNS strings");
|
||||
|
||||
#ifdef USE_CACHEDB
|
||||
daemon->env->cachedb_enabled = cachedb_is_enabled(&daemon->mods,
|
||||
daemon->env);
|
||||
#endif
|
||||
/* response-ip-xxx options don't work as expected without the respip
|
||||
* module. To avoid run-time operational surprise we reject such
|
||||
* configuration. */
|
||||
|
@ -659,7 +659,9 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
if(rep->ttl < timenow) {
|
||||
/* Check if we need to serve expired now */
|
||||
if(worker->env.cfg->serve_expired &&
|
||||
!worker->env.cfg->serve_expired_client_timeout) {
|
||||
!worker->env.cfg->serve_expired_client_timeout &&
|
||||
!(worker->env.cachedb_enabled &&
|
||||
worker->env.cfg->cachedb_check_when_serve_expired)) {
|
||||
if(worker->env.cfg->serve_expired_ttl &&
|
||||
rep->serve_expired_ttl < timenow)
|
||||
return 0;
|
||||
|
@ -1,3 +1,8 @@
|
||||
10 April 2024: Wouter
|
||||
- Implement cachedb-check-when-serve-expired: yes option, default
|
||||
is enabled. When serve expired is enabled with cachedb, it first
|
||||
checks cachedb before serving the expired response.
|
||||
|
||||
9 April 2024: Yorgos
|
||||
- Merge #1043 from xiaoxiaoafeifei: Add loongarch support; updates
|
||||
config.guess(2024-01-01) and config.sub(2024-01-01), verified
|
||||
|
@ -1253,6 +1253,9 @@ remote-control:
|
||||
# secret-seed: "default"
|
||||
# # if the backend should be read from, but not written to.
|
||||
# cachedb-no-store: no
|
||||
# # if the cachedb should be checked before a serve-expired response is
|
||||
# # given, when serve-expired is enabled.
|
||||
# cachedb-check-when-serve-expired: yes
|
||||
#
|
||||
# # For "redis" backend:
|
||||
# # (to enable, use --with-libhiredis to configure before compiling)
|
||||
|
@ -2700,6 +2700,14 @@ This option defaults to "default".
|
||||
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.
|
||||
.TP
|
||||
.B cachedb-check-when-serve-expired: \fI<yes or no>\fR
|
||||
If enabled, the cachedb is checked before an expired response is returned.
|
||||
When serve-expired is enabled, without serve-expired-client-timeout, it then
|
||||
does not immediately respond with an expired response from cache, but instead
|
||||
first checks the cachedb for valid contents, and if so returns it. If the
|
||||
cachedb also has no valid contents, the serve expired response is sent.
|
||||
The default is yes.
|
||||
.P
|
||||
The following
|
||||
.B cachedb
|
||||
|
@ -385,7 +385,7 @@ mesh_serve_expired_init(struct mesh_state* mstate, int timeout)
|
||||
&mesh_serve_expired_lookup;
|
||||
|
||||
/* In case this timer already popped, start it again */
|
||||
if(!mstate->s.serve_expired_data->timer) {
|
||||
if(!mstate->s.serve_expired_data->timer && timeout != -1) {
|
||||
mstate->s.serve_expired_data->timer = comm_timer_create(
|
||||
mstate->s.env->worker_base, mesh_serve_expired_callback, mstate);
|
||||
if(!mstate->s.serve_expired_data->timer)
|
||||
@ -511,6 +511,15 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
log_err("mesh_new_client: out of memory initializing serve expired");
|
||||
goto servfail_mem;
|
||||
}
|
||||
if(!timeout && mesh->env->cfg->serve_expired &&
|
||||
!mesh->env->cfg->serve_expired_client_timeout &&
|
||||
(mesh->env->cachedb_enabled &&
|
||||
mesh->env->cfg->cachedb_check_when_serve_expired)) {
|
||||
if(!mesh_serve_expired_init(s, -1)) {
|
||||
log_err("mesh_new_client: out of memory initializing serve expired");
|
||||
goto servfail_mem;
|
||||
}
|
||||
}
|
||||
/* update statistics */
|
||||
if(was_detached) {
|
||||
log_assert(mesh->num_detached_states > 0);
|
||||
@ -616,6 +625,16 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
mesh_state_delete(&s->s);
|
||||
return 0;
|
||||
}
|
||||
if(!timeout && mesh->env->cfg->serve_expired &&
|
||||
!mesh->env->cfg->serve_expired_client_timeout &&
|
||||
(mesh->env->cachedb_enabled &&
|
||||
mesh->env->cfg->cachedb_check_when_serve_expired)) {
|
||||
if(!mesh_serve_expired_init(s, -1)) {
|
||||
if(added)
|
||||
mesh_state_delete(&s->s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* update statistics */
|
||||
if(was_detached) {
|
||||
log_assert(mesh->num_detached_states > 0);
|
||||
@ -2238,6 +2257,12 @@ mesh_serve_expired_callback(void* arg)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mesh_respond_serve_expired(struct mesh_state* mstate)
|
||||
{
|
||||
mesh_serve_expired_callback(mstate);
|
||||
}
|
||||
|
||||
int mesh_jostle_exceeded(struct mesh_area* mesh)
|
||||
{
|
||||
if(mesh->all.count < mesh->max_reply_states)
|
||||
|
@ -690,4 +690,10 @@ mesh_serve_expired_lookup(struct module_qstate* qstate,
|
||||
*/
|
||||
int mesh_jostle_exceeded(struct mesh_area* mesh);
|
||||
|
||||
/**
|
||||
* Give the serve expired responses.
|
||||
* @param mstate: mesh state for query that has serve_expired_data.
|
||||
*/
|
||||
void mesh_respond_serve_expired(struct mesh_state* mstate);
|
||||
|
||||
#endif /* SERVICES_MESH_H */
|
||||
|
@ -385,6 +385,7 @@ config_create(void)
|
||||
if(!(cfg->cachedb_backend = strdup("testframe"))) goto error_exit;
|
||||
if(!(cfg->cachedb_secret = strdup("default"))) goto error_exit;
|
||||
cfg->cachedb_no_store = 0;
|
||||
cfg->cachedb_check_when_serve_expired = 1;
|
||||
#ifdef USE_REDIS
|
||||
if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit;
|
||||
cfg->redis_server_path = NULL;
|
||||
@ -830,6 +831,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
else S_YNO("cachedb-no-store:", cachedb_no_store)
|
||||
else S_YNO("cachedb-check-when-serve-expired:", cachedb_check_when_serve_expired)
|
||||
#endif /* USE_CACHEDB */
|
||||
else if(strcmp(opt, "define-tag:") ==0) {
|
||||
return config_add_tag(cfg, val);
|
||||
@ -1322,6 +1324,7 @@ config_get_option(struct config_file* cfg, const char* opt,
|
||||
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)
|
||||
else O_YNO(opt, "cachedb-check-when-serve-expired", cachedb_check_when_serve_expired)
|
||||
#ifdef USE_REDIS
|
||||
else O_STR(opt, "redis-server-host", redis_server_host)
|
||||
else O_DEC(opt, "redis-server-port", redis_server_port)
|
||||
|
@ -707,6 +707,8 @@ struct config_file {
|
||||
char* cachedb_secret;
|
||||
/** cachedb that does not store, but only reads from database, if on */
|
||||
int cachedb_no_store;
|
||||
/** cachedb check before serving serve-expired response */
|
||||
int cachedb_check_when_serve_expired;
|
||||
#ifdef USE_REDIS
|
||||
/** redis server's IP address or host name */
|
||||
char* redis_server_host;
|
||||
|
@ -561,6 +561,7 @@ 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) }
|
||||
cachedb-check-when-serve-expired{COLON} { YDVAR(1, VAR_CACHEDB_CHECK_WHEN_SERVE_EXPIRED) }
|
||||
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) }
|
||||
|
@ -201,7 +201,7 @@ extern struct config_parser_state* cfg_parser;
|
||||
%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 VAR_CACHEDB_NO_STORE
|
||||
%token VAR_LOG_DESTADDR
|
||||
%token VAR_LOG_DESTADDR VAR_CACHEDB_CHECK_WHEN_SERVE_EXPIRED
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
@ -3734,7 +3734,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 |
|
||||
cachedb_no_store | redis_logical_db
|
||||
cachedb_no_store | redis_logical_db | cachedb_check_when_serve_expired
|
||||
;
|
||||
cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG
|
||||
{
|
||||
@ -3773,6 +3773,19 @@ cachedb_no_store: VAR_CACHEDB_NO_STORE STRING_ARG
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
cachedb_check_when_serve_expired: VAR_CACHEDB_CHECK_WHEN_SERVE_EXPIRED STRING_ARG
|
||||
{
|
||||
#ifdef USE_CACHEDB
|
||||
OUTYY(("P(cachedb_check_when_serve_expired:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
else cfg_parser->cfg->cachedb_check_when_serve_expired = (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)
|
||||
|
@ -537,6 +537,10 @@ struct module_env {
|
||||
/** EDNS client string information */
|
||||
struct edns_strings* edns_strings;
|
||||
|
||||
#ifdef USE_CACHEDB
|
||||
/** the cachedb enabled value, copied and stored here. */
|
||||
int cachedb_enabled;
|
||||
#endif
|
||||
/* Make every mesh state unique, do not aggregate mesh states. */
|
||||
int unique_mesh;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user