summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
Diffstat (limited to 'daemon')
-rw-r--r--daemon/daemon.c9
-rw-r--r--daemon/daemon.h2
-rw-r--r--daemon/remote.c40
-rw-r--r--daemon/stats.c8
-rw-r--r--daemon/unbound.c25
-rw-r--r--daemon/worker.c146
6 files changed, 154 insertions, 76 deletions
diff --git a/daemon/daemon.c b/daemon/daemon.c
index 0b1200a2e00a..8b0fc3483ab7 100644
--- a/daemon/daemon.c
+++ b/daemon/daemon.c
@@ -617,7 +617,8 @@ daemon_fork(struct daemon* daemon)
have_view_respip_cfg;
/* read auth zonefiles */
- if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1))
+ if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1,
+ &daemon->use_rpz))
fatal_exit("auth_zones could not be setup");
/* setup modules */
@@ -629,6 +630,12 @@ daemon_fork(struct daemon* daemon)
if(daemon->use_response_ip &&
modstack_find(&daemon->mods, "respip") < 0)
fatal_exit("response-ip options require respip module");
+ /* RPZ response ip triggers don't work as expected without the respip
+ * module. To avoid run-time operational surprise we reject such
+ * configuration. */
+ if(daemon->use_rpz &&
+ modstack_find(&daemon->mods, "respip") < 0)
+ fatal_exit("RPZ requires the respip module");
/* first create all the worker structures, so we can pass
* them to the newly created threads.
diff --git a/daemon/daemon.h b/daemon/daemon.h
index 5749dbef8fbf..3effbafb7918 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -132,6 +132,8 @@ struct daemon {
struct respip_set* respip_set;
/** some response-ip tags or actions are configured if true */
int use_response_ip;
+ /** some RPZ policies are configured */
+ int use_rpz;
#ifdef USE_DNSCRYPT
/** the dnscrypt environment */
struct dnsc_env* dnscenv;
diff --git a/daemon/remote.c b/daemon/remote.c
index 25547f5705d9..1782a39cad7c 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -69,6 +69,7 @@
#include "services/mesh.h"
#include "services/localzone.h"
#include "services/authzone.h"
+#include "services/rpz.h"
#include "util/storage/slabhash.h"
#include "util/fptr_wlist.h"
#include "util/data/dname.h"
@@ -719,8 +720,8 @@ print_stats(RES* ssl, const char* nm, struct ub_stats_info* s)
(unsigned long)s->svr.num_queries_missed_cache)) return 0;
if(!ssl_printf(ssl, "%s.num.prefetch"SQ"%lu\n", nm,
(unsigned long)s->svr.num_queries_prefetch)) return 0;
- if(!ssl_printf(ssl, "%s.num.zero_ttl"SQ"%lu\n", nm,
- (unsigned long)s->svr.zero_ttl_responses)) return 0;
+ if(!ssl_printf(ssl, "%s.num.expired"SQ"%lu\n", nm,
+ (unsigned long)s->svr.ans_expired)) return 0;
if(!ssl_printf(ssl, "%s.num.recursivereplies"SQ"%lu\n", nm,
(unsigned long)s->mesh_replies_sent)) return 0;
#ifdef USE_DNSCRYPT
@@ -1045,6 +1046,16 @@ print_ext(RES* ssl, struct ub_stats_info* s)
(unsigned)s->svr.infra_cache_count)) return 0;
if(!ssl_printf(ssl, "key.cache.count"SQ"%u\n",
(unsigned)s->svr.key_cache_count)) return 0;
+ /* applied RPZ actions */
+ for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++) {
+ if(i == RPZ_NO_OVERRIDE_ACTION)
+ continue;
+ if(inhibit_zero && s->svr.rpz_action[i] == 0)
+ continue;
+ if(!ssl_printf(ssl, "num.rpz.action.%s"SQ"%lu\n",
+ rpz_action_to_string(i),
+ (unsigned long)s->svr.rpz_action[i])) return 0;
+ }
#ifdef USE_DNSCRYPT
if(!ssl_printf(ssl, "dnscrypt_shared_secret.cache.count"SQ"%u\n",
(unsigned)s->svr.shared_secret_cache_count)) return 0;
@@ -1479,6 +1490,27 @@ do_view_data_remove(RES* ssl, struct worker* worker, char* arg)
lock_rw_unlock(&v->lock);
}
+/** Remove RR data from stdin from view */
+static void
+do_view_datas_remove(RES* ssl, struct worker* worker, char* arg)
+{
+ struct view* v;
+ v = views_find_view(worker->daemon->views,
+ arg, 1 /* get write lock*/);
+ if(!v) {
+ ssl_printf(ssl,"no view with name: %s\n", arg);
+ return;
+ }
+ if(!v->local_zones){
+ lock_rw_unlock(&v->lock);
+ ssl_printf(ssl, "removed 0 datas\n");
+ return;
+ }
+
+ do_datas_remove(ssl, v->local_zones);
+ lock_rw_unlock(&v->lock);
+}
+
/** cache lookup of nameservers */
static void
do_lookup(RES* ssl, struct worker* worker, char* arg)
@@ -2506,8 +2538,10 @@ do_auth_zone_transfer(RES* ssl, struct worker* worker, char* arg)
if(!az || !auth_zones_startprobesequence(az, &worker->env, nm, nmlen,
LDNS_RR_CLASS_IN)) {
(void)ssl_printf(ssl, "error zone xfr task not found %s\n", arg);
+ free(nm);
return;
}
+ free(nm);
send_ok(ssl);
}
@@ -2989,6 +3023,8 @@ execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd,
do_view_zone_add(ssl, worker, skipwhite(p+15));
} else if(cmdcmp(p, "view_local_data_remove", 22)) {
do_view_data_remove(ssl, worker, skipwhite(p+22));
+ } else if(cmdcmp(p, "view_local_datas_remove", 23)){
+ do_view_datas_remove(ssl, worker, skipwhite(p+23));
} else if(cmdcmp(p, "view_local_data", 15)) {
do_view_data_add(ssl, worker, skipwhite(p+15));
} else if(cmdcmp(p, "view_local_datas", 16)) {
diff --git a/daemon/stats.c b/daemon/stats.c
index a01fb6d342ca..a568ba070a57 100644
--- a/daemon/stats.c
+++ b/daemon/stats.c
@@ -271,8 +271,10 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
s->svr.ans_secure += (long long)worker->env.mesh->ans_secure;
s->svr.ans_bogus += (long long)worker->env.mesh->ans_bogus;
s->svr.ans_rcode_nodata += (long long)worker->env.mesh->ans_nodata;
- for(i=0; i<16; i++)
+ for(i=0; i<UB_STATS_RCODE_NUM; i++)
s->svr.ans_rcode[i] += (long long)worker->env.mesh->ans_rcode[i];
+ for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++)
+ s->svr.rpz_action[i] += (long long)worker->env.mesh->rpz_action[i];
timehist_export(worker->env.mesh->histogram, s->svr.hist,
NUM_BUCKETS_HIST);
/* values from outside network */
@@ -398,6 +400,7 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache;
total->svr.num_queries_prefetch += a->svr.num_queries_prefetch;
total->svr.sum_query_list_size += a->svr.sum_query_list_size;
+ total->svr.ans_expired += a->svr.ans_expired;
#ifdef USE_DNSCRYPT
total->svr.num_query_dnscrypt_crypted += a->svr.num_query_dnscrypt_crypted;
total->svr.num_query_dnscrypt_cert += a->svr.num_query_dnscrypt_cert;
@@ -430,7 +433,6 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
total->svr.qEDNS += a->svr.qEDNS;
total->svr.qEDNS_DO += a->svr.qEDNS_DO;
total->svr.ans_rcode_nodata += a->svr.ans_rcode_nodata;
- total->svr.zero_ttl_responses += a->svr.zero_ttl_responses;
total->svr.ans_secure += a->svr.ans_secure;
total->svr.ans_bogus += a->svr.ans_bogus;
total->svr.unwanted_replies += a->svr.unwanted_replies;
@@ -446,6 +448,8 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
total->svr.ans_rcode[i] += a->svr.ans_rcode[i];
for(i=0; i<NUM_BUCKETS_HIST; i++)
total->svr.hist[i] += a->svr.hist[i];
+ for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++)
+ total->svr.rpz_action[i] += a->svr.rpz_action[i];
}
total->mesh_num_states += a->mesh_num_states;
diff --git a/daemon/unbound.c b/daemon/unbound.c
index beffb57005fa..af76fc84fe51 100644
--- a/daemon/unbound.c
+++ b/daemon/unbound.c
@@ -259,21 +259,10 @@ checkrlimits(struct config_file* cfg)
#endif /* S_SPLINT_S */
}
-/** set default logfile identity based on value from argv[0] at startup **/
-static void
-log_ident_set_fromdefault(struct config_file* cfg,
- const char *log_default_identity)
-{
- if(cfg->log_identity == NULL || cfg->log_identity[0] == 0)
- log_ident_set(log_default_identity);
- else
- log_ident_set(cfg->log_identity);
-}
-
/** set verbosity, check rlimits, cache settings */
static void
-apply_settings(struct daemon* daemon, struct config_file* cfg,
- int cmdline_verbose, int debug_mode, const char* log_default_identity)
+apply_settings(struct daemon* daemon, struct config_file* cfg,
+ int cmdline_verbose, int debug_mode)
{
/* apply if they have changed */
verbosity = cmdline_verbose + cfg->verbosity;
@@ -289,7 +278,7 @@ apply_settings(struct daemon* daemon, struct config_file* cfg,
log_warn("use-systemd and do-daemonize should not be enabled at the same time");
}
- log_ident_set_fromdefault(cfg, log_default_identity);
+ log_ident_set_or_default(cfg->log_identity);
}
#ifdef HAVE_KILL
@@ -639,11 +628,10 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
* @param cmdline_verbose: verbosity resulting from commandline -v.
* These increase verbosity as specified in the config file.
* @param debug_mode: if set, do not daemonize.
- * @param log_default_identity: Default identity to report in logs
* @param need_pidfile: if false, no pidfile is checked or created.
*/
static void
-run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char* log_default_identity, int need_pidfile)
+run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pidfile)
{
struct config_file* cfg = NULL;
struct daemon* daemon = NULL;
@@ -667,7 +655,7 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char*
"or unbound-checkconf", cfgfile);
log_warn("Continuing with default config settings");
}
- apply_settings(daemon, cfg, cmdline_verbose, debug_mode, log_default_identity);
+ apply_settings(daemon, cfg, cmdline_verbose, debug_mode);
if(!done_setup)
config_lookup_uid(cfg);
@@ -733,6 +721,7 @@ main(int argc, char* argv[])
log_init(NULL, 0, NULL);
log_ident_default = strrchr(argv[0],'/')?strrchr(argv[0],'/')+1:argv[0];
+ log_ident_set_default(log_ident_default);
log_ident_set(log_ident_default);
/* parse the options */
while( (c=getopt(argc, argv, "c:dhpvw:V")) != -1) {
@@ -783,7 +772,7 @@ main(int argc, char* argv[])
return 1;
}
- run_daemon(cfgfile, cmdline_verbose, debug_mode, log_ident_default, need_pidfile);
+ run_daemon(cfgfile, cmdline_verbose, debug_mode, need_pidfile);
log_init(NULL, 0, NULL); /* close logfile */
#ifndef unbound_testbound
if(log_get_lock()) {
diff --git a/daemon/worker.c b/daemon/worker.c
index e2ce0e87009b..eb7fdf2f576d 100644
--- a/daemon/worker.c
+++ b/daemon/worker.c
@@ -61,6 +61,7 @@
#include "services/authzone.h"
#include "services/mesh.h"
#include "services/localzone.h"
+#include "services/rpz.h"
#include "util/data/msgparse.h"
#include "util/data/msgencode.h"
#include "util/data/dname.h"
@@ -572,9 +573,10 @@ static int
apply_respip_action(struct worker* worker, const struct query_info* qinfo,
struct respip_client_info* cinfo, struct reply_info* rep,
struct comm_reply* repinfo, struct ub_packed_rrset_key** alias_rrset,
- struct reply_info** encode_repp)
+ struct reply_info** encode_repp, struct auth_zones* az)
{
- struct respip_action_info actinfo = {respip_none, NULL};
+ struct respip_action_info actinfo = {0};
+ actinfo.action = respip_none;
if(qinfo->qtype != LDNS_RR_TYPE_A &&
qinfo->qtype != LDNS_RR_TYPE_AAAA &&
@@ -582,7 +584,7 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
return 1;
if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, &actinfo,
- alias_rrset, 0, worker->scratchpad))
+ alias_rrset, 0, worker->scratchpad, az))
return 0;
/* xxx_deny actions mean dropping the reply, unless the original reply
@@ -595,9 +597,19 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
/* If address info is returned, it means the action should be an
* 'inform' variant and the information should be logged. */
if(actinfo.addrinfo) {
- respip_inform_print(actinfo.addrinfo, qinfo->qname,
+ respip_inform_print(&actinfo, qinfo->qname,
qinfo->qtype, qinfo->qclass, qinfo->local_alias,
repinfo);
+
+ if(worker->stats.extended && actinfo.rpz_used) {
+ if(actinfo.rpz_disabled)
+ worker->stats.rpz_action[RPZ_DISABLED_ACTION]++;
+ if(actinfo.rpz_cname_override)
+ worker->stats.rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
+ else
+ worker->stats.rpz_action[
+ respip_action_to_rpz_action(actinfo.action)]++;
+ }
}
return 1;
@@ -613,10 +625,10 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
* be completely dropped, '*need_drop' will be set to 1. */
static int
answer_from_cache(struct worker* worker, struct query_info* qinfo,
- struct respip_client_info* cinfo, int* need_drop,
- struct ub_packed_rrset_key** alias_rrset,
+ struct respip_client_info* cinfo, int* need_drop, int* is_expired_answer,
+ int* is_secure_answer, struct ub_packed_rrset_key** alias_rrset,
struct reply_info** partial_repp,
- struct reply_info* rep, uint16_t id, uint16_t flags,
+ struct reply_info* rep, uint16_t id, uint16_t flags,
struct comm_reply* repinfo, struct edns_data* edns)
{
struct edns_data edns_bak;
@@ -624,38 +636,37 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
uint16_t udpsize = edns->udp_size;
struct reply_info* encode_rep = rep;
struct reply_info* partial_rep = *partial_repp;
- int secure;
int must_validate = (!(flags&BIT_CD) || worker->env.cfg->ignore_cd)
&& worker->env.need_to_validate;
- *partial_repp = NULL; /* avoid accidental further pass */
- if(worker->env.cfg->serve_expired) {
- if(worker->env.cfg->serve_expired_ttl &&
- rep->serve_expired_ttl < timenow)
- return 0;
- if(!rrset_array_lock(rep->ref, rep->rrset_count, 0))
- return 0;
- /* below, rrsets with ttl before timenow become TTL 0 in
- * the response */
- /* This response was served with zero TTL */
- if (timenow >= rep->ttl) {
- worker->stats.zero_ttl_responses++;
- }
- } else {
- /* see if it is possible */
- if(rep->ttl < timenow) {
+ *partial_repp = NULL; /* avoid accidental further pass */
+
+ /* Check TTL */
+ 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) {
+ if(worker->env.cfg->serve_expired_ttl &&
+ rep->serve_expired_ttl < timenow)
+ return 0;
+ if(!rrset_array_lock(rep->ref, rep->rrset_count, 0))
+ return 0;
+ *is_expired_answer = 1;
+ } else {
/* the rrsets may have been updated in the meantime.
* we will refetch the message format from the
- * authoritative server
+ * authoritative server
*/
return 0;
}
+ } else {
if(!rrset_array_lock(rep->ref, rep->rrset_count, timenow))
return 0;
- /* locked and ids and ttls are OK. */
}
+ /* locked and ids and ttls are OK. */
+
/* check CNAME chain (if any) */
- if(rep->an_numrrsets > 0 && (rep->rrsets[0]->rk.type ==
- htons(LDNS_RR_TYPE_CNAME) || rep->rrsets[0]->rk.type ==
+ if(rep->an_numrrsets > 0 && (rep->rrsets[0]->rk.type ==
+ htons(LDNS_RR_TYPE_CNAME) || rep->rrsets[0]->rk.type ==
htons(LDNS_RR_TYPE_DNAME))) {
if(!reply_check_cname_chain(qinfo, rep)) {
/* cname chain invalid, redo iterator steps */
@@ -674,31 +685,31 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, rep,
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad))
goto bail_out;
- error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
+ error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, id, flags, edns);
- rrset_array_unlock_touch(worker->env.rrset_cache,
+ rrset_array_unlock_touch(worker->env.rrset_cache,
worker->scratchpad, rep->ref, rep->rrset_count);
if(worker->stats.extended) {
worker->stats.ans_bogus ++;
worker->stats.ans_rcode[LDNS_RCODE_SERVFAIL] ++;
}
return 1;
- } else if( rep->security == sec_status_unchecked && must_validate) {
+ } else if(rep->security == sec_status_unchecked && must_validate) {
verbose(VERB_ALGO, "Cache reply: unchecked entry needs "
"validation");
goto bail_out; /* need to validate cache entry first */
} else if(rep->security == sec_status_secure) {
- if(reply_all_rrsets_secure(rep))
- secure = 1;
- else {
+ if(reply_all_rrsets_secure(rep)) {
+ *is_secure_answer = 1;
+ } else {
if(must_validate) {
verbose(VERB_ALGO, "Cache reply: secure entry"
" changed status");
goto bail_out; /* rrset changed, re-verify */
}
- secure = 0;
+ *is_secure_answer = 0;
}
- } else secure = 0;
+ } else *is_secure_answer = 0;
edns_bak = *edns;
edns->edns_version = EDNS_ADVERTISED_VERSION;
@@ -709,17 +720,21 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
(int)(flags&LDNS_RCODE_MASK), edns, repinfo, worker->scratchpad))
goto bail_out;
*alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */
- if(worker->daemon->use_response_ip && !partial_rep &&
- !apply_respip_action(worker, qinfo, cinfo, rep, repinfo, alias_rrset,
- &encode_rep)) {
+ if((worker->daemon->use_response_ip || worker->daemon->use_rpz) &&
+ !partial_rep && !apply_respip_action(worker, qinfo, cinfo, rep,
+ repinfo, alias_rrset,
+ &encode_rep, worker->env.auth_zones)) {
goto bail_out;
} else if(partial_rep &&
!respip_merge_cname(partial_rep, qinfo, rep, cinfo,
- must_validate, &encode_rep, worker->scratchpad)) {
+ must_validate, &encode_rep, worker->scratchpad,
+ worker->env.auth_zones)) {
goto bail_out;
}
- if(encode_rep != rep)
- secure = 0; /* if rewritten, it can't be considered "secure" */
+ if(encode_rep != rep) {
+ /* if rewritten, it can't be considered "secure" */
+ *is_secure_answer = 0;
+ }
if(!encode_rep || *alias_rrset) {
if(!encode_rep)
*need_drop = 1;
@@ -736,7 +751,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
repinfo->c, worker->scratchpad) ||
!reply_info_answer_encode(qinfo, encode_rep, id, flags,
repinfo->c->buffer, timenow, 1, worker->scratchpad,
- udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
+ udpsize, edns, (int)(edns->bits & EDNS_DO), *is_secure_answer)) {
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad))
edns->opt_list = NULL;
@@ -747,10 +762,6 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
* is bad while holding locks. */
rrset_array_unlock_touch(worker->env.rrset_cache, worker->scratchpad,
rep->ref, rep->rrset_count);
- if(worker->stats.extended) {
- if(secure) worker->stats.ans_secure++;
- server_stats_insrcode(&worker->stats, repinfo->c->buffer);
- }
/* go and return this buffer to the client */
return 1;
@@ -1085,6 +1096,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
struct acl_addr* acladdr;
int rc = 0;
int need_drop = 0;
+ int is_expired_answer = 0;
+ int is_secure_answer = 0;
/* We might have to chase a CNAME chain internally, in which case
* we'll have up to two replies and combine them to build a complete
* answer. These variables control this case. */
@@ -1365,6 +1378,18 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
goto send_reply;
}
if(worker->env.auth_zones &&
+ rpz_apply_qname_trigger(worker->env.auth_zones,
+ &worker->env, &qinfo, &edns, c->buffer, worker->scratchpad,
+ repinfo, acladdr->taglist, acladdr->taglen, &worker->stats)) {
+ regional_free_all(worker->scratchpad);
+ if(sldns_buffer_limit(c->buffer) == 0) {
+ comm_point_drop_reply(repinfo);
+ return 0;
+ }
+ server_stats_insrcode(&worker->stats, c->buffer);
+ goto send_reply;
+ }
+ if(worker->env.auth_zones &&
auth_zones_answer(worker->env.auth_zones, &worker->env,
&qinfo, &edns, repinfo, c->buffer, worker->scratchpad)) {
regional_free_all(worker->scratchpad);
@@ -1434,7 +1459,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
/* If we may apply IP-based actions to the answer, build the client
* information. As this can be expensive, skip it if there is
* absolutely no possibility of it. */
- if(worker->daemon->use_response_ip &&
+ if((worker->daemon->use_response_ip || worker->daemon->use_rpz) &&
(qinfo.qtype == LDNS_RR_TYPE_A ||
qinfo.qtype == LDNS_RR_TYPE_AAAA ||
qinfo.qtype == LDNS_RR_TYPE_ANY)) {
@@ -1455,12 +1480,14 @@ lookup_cache:
* each pass. We should still pass the original qinfo to
* answer_from_cache(), however, since it's used to build the reply. */
if(!edns_bypass_cache_stage(edns.opt_list, &worker->env)) {
+ is_expired_answer = 0;
+ is_secure_answer = 0;
h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
if((e=slabhash_lookup(worker->env.msg_cache, h, lookup_qinfo, 0))) {
/* answer from cache - we have acquired a readlock on it */
if(answer_from_cache(worker, &qinfo,
- cinfo, &need_drop, &alias_rrset, &partial_rep,
- (struct reply_info*)e->data,
+ cinfo, &need_drop, &is_expired_answer, &is_secure_answer,
+ &alias_rrset, &partial_rep, (struct reply_info*)e->data,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
&edns)) {
@@ -1468,9 +1495,11 @@ lookup_cache:
* Note that if there is more than one pass
* its qname must be that used for cache
* lookup. */
- if((worker->env.cfg->prefetch || worker->env.cfg->serve_expired)
- && *worker->env.now >=
- ((struct reply_info*)e->data)->prefetch_ttl) {
+ if((worker->env.cfg->prefetch && *worker->env.now >=
+ ((struct reply_info*)e->data)->prefetch_ttl) ||
+ (worker->env.cfg->serve_expired &&
+ *worker->env.now >= ((struct reply_info*)e->data)->ttl)) {
+
time_t leeway = ((struct reply_info*)e->
data)->ttl - *worker->env.now;
if(((struct reply_info*)e->data)->ttl
@@ -1555,6 +1584,13 @@ send_reply_rc:
comm_point_drop_reply(repinfo);
return 0;
}
+ if(is_expired_answer) {
+ worker->stats.ans_expired++;
+ }
+ if(worker->stats.extended) {
+ if(is_secure_answer) worker->stats.ans_secure++;
+ server_stats_insrcode(&worker->stats, repinfo->c->buffer);
+ }
#ifdef USE_DNSTAP
if(worker->dtenv.log_client_response_messages)
dt_msg_send_client_response(&worker->dtenv, &repinfo->addr,
@@ -1830,6 +1866,10 @@ worker_init(struct worker* worker, struct config_file *cfg,
return 0;
}
worker->env.mesh = mesh_create(&worker->daemon->mods, &worker->env);
+ /* Pass on daemon variables that we would need in the mesh area */
+ worker->env.mesh->use_response_ip = worker->daemon->use_response_ip;
+ worker->env.mesh->use_rpz = worker->daemon->use_rpz;
+
worker->env.detach_subs = &mesh_detach_subs;
worker->env.attach_sub = &mesh_attach_sub;
worker->env.add_sub = &mesh_add_sub;