summaryrefslogtreecommitdiff
path: root/services/mesh.c
diff options
context:
space:
mode:
Diffstat (limited to 'services/mesh.c')
-rw-r--r--services/mesh.c54
1 files changed, 36 insertions, 18 deletions
diff --git a/services/mesh.c b/services/mesh.c
index 41aba74ab260..c6bb9ef2bc63 100644
--- a/services/mesh.c
+++ b/services/mesh.c
@@ -55,6 +55,7 @@
#include "util/fptr_wlist.h"
#include "util/alloc.h"
#include "util/config_file.h"
+#include "util/edns.h"
#include "sldns/sbuffer.h"
#include "sldns/wire2str.h"
#include "services/localzone.h"
@@ -385,7 +386,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
if(!s) {
log_err("mesh_state_create: out of memory; SERVFAIL");
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL,
- LDNS_RCODE_SERVFAIL, edns, mesh->env->scratch))
+ LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
edns->opt_list = NULL;
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
@@ -401,7 +402,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
if(!s->s.edns_opts_front_in) {
log_err("mesh_state_create: out of memory; SERVFAIL");
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL,
- NULL, LDNS_RCODE_SERVFAIL, edns, mesh->env->scratch))
+ NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
edns->opt_list = NULL;
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
@@ -429,7 +430,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo)) {
log_err("mesh_new_client: out of memory; SERVFAIL");
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s,
- NULL, LDNS_RCODE_SERVFAIL, edns, mesh->env->scratch))
+ NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
edns->opt_list = NULL;
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
@@ -631,8 +632,8 @@ void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
mesh_run(mesh, e->qstate->mesh_info, event, e);
}
-struct mesh_state*
-mesh_state_create(struct module_env* env, struct query_info* qinfo,
+struct mesh_state*
+mesh_state_create(struct module_env* env, struct query_info* qinfo,
struct respip_client_info* cinfo, uint16_t qflags, int prime,
int valrec)
{
@@ -693,6 +694,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
mstate->s.no_cache_lookup = 0;
mstate->s.no_cache_store = 0;
mstate->s.need_refetch = 0;
+ mstate->s.was_ratelimited = 0;
/* init modules */
for(i=0; i<env->mesh->mods.num; i++) {
@@ -740,7 +742,7 @@ mesh_state_cleanup(struct mesh_state* mstate)
mstate->cb_list = cb->next;
fptr_ok(fptr_whitelist_mesh_cb(cb->cb));
(*cb->cb)(cb->cb_arg, LDNS_RCODE_SERVFAIL, NULL,
- sec_status_unchecked, NULL);
+ sec_status_unchecked, NULL, 0);
mesh->num_reply_addrs--;
}
}
@@ -968,7 +970,8 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
{
int secure;
char* reason = NULL;
- /* bogus messages are not made into servfail, sec_status passed
+ int was_ratelimited = m->s.was_ratelimited;
+ /* bogus messages are not made into servfail, sec_status passed
* to the callback function */
if(rep && rep->security == sec_status_secure)
secure = 1;
@@ -977,22 +980,23 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
rcode = LDNS_RCODE_SERVFAIL;
if(!rcode && (rep->security == sec_status_bogus ||
rep->security == sec_status_secure_sentinel_fail)) {
- if(!(reason = errinf_to_str(&m->s)))
+ if(!(reason = errinf_to_str_bogus(&m->s)))
rcode = LDNS_RCODE_SERVFAIL;
}
/* send the reply */
if(rcode) {
if(rcode == LDNS_RCODE_SERVFAIL) {
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
- rep, rcode, &r->edns, m->s.region))
+ rep, rcode, &r->edns, NULL, m->s.region))
r->edns.opt_list = NULL;
} else {
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
- &r->edns, m->s.region))
+ &r->edns, NULL, m->s.region))
r->edns.opt_list = NULL;
}
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
- (*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL);
+ (*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL,
+ was_ratelimited);
} else {
size_t udp_size = r->edns.udp_size;
sldns_buffer_clear(r->buf);
@@ -1002,7 +1006,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
r->edns.bits &= EDNS_DO;
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
- LDNS_RCODE_NOERROR, &r->edns, m->s.region) ||
+ LDNS_RCODE_NOERROR, &r->edns, NULL, m->s.region) ||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r->buf, 0, 1,
m->s.env->scratch, udp_size, &r->edns,
@@ -1010,11 +1014,11 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
{
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
(*r->cb)(r->cb_arg, LDNS_RCODE_SERVFAIL, r->buf,
- sec_status_unchecked, NULL);
+ sec_status_unchecked, NULL, 0);
} else {
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
(*r->cb)(r->cb_arg, LDNS_RCODE_NOERROR, r->buf,
- rep->security, reason);
+ rep->security, reason, was_ratelimited);
}
}
free(reason);
@@ -1080,11 +1084,11 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
m->s.qinfo.local_alias = r->local_alias;
if(rcode == LDNS_RCODE_SERVFAIL) {
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
- rep, rcode, &r->edns, m->s.region))
+ rep, rcode, &r->edns, NULL, m->s.region))
r->edns.opt_list = NULL;
} else {
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
- &r->edns, m->s.region))
+ &r->edns, NULL, m->s.region))
r->edns.opt_list = NULL;
}
error_encode(r->query_reply.c->buffer, rcode, &m->s.qinfo,
@@ -1099,14 +1103,17 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
m->s.qinfo.qname = r->qname;
m->s.qinfo.local_alias = r->local_alias;
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
- LDNS_RCODE_NOERROR, &r->edns, m->s.region) ||
+ LDNS_RCODE_NOERROR, &r->edns, NULL, m->s.region) ||
+ !apply_edns_options(&r->edns, &edns_bak,
+ m->s.env->cfg, r->query_reply.c,
+ m->s.region) ||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r->query_reply.c->buffer, 0, 1,
m->s.env->scratch, udp_size, &r->edns,
(int)(r->edns.bits & EDNS_DO), secure))
{
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
- rep, LDNS_RCODE_SERVFAIL, &r->edns, m->s.region))
+ rep, LDNS_RCODE_SERVFAIL, &r->edns, NULL, m->s.region))
r->edns.opt_list = NULL;
error_encode(r->query_reply.c->buffer,
LDNS_RCODE_SERVFAIL, &m->s.qinfo, r->qid,
@@ -1148,6 +1155,15 @@ void mesh_query_done(struct mesh_state* mstate)
struct mesh_cb* c;
struct reply_info* rep = (mstate->s.return_msg?
mstate->s.return_msg->rep:NULL);
+ if((mstate->s.return_rcode == LDNS_RCODE_SERVFAIL ||
+ (rep && FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_SERVFAIL))
+ && mstate->s.env->cfg->log_servfail
+ && !mstate->s.env->cfg->val_log_squelch) {
+ char* err = errinf_to_str_servfail(&mstate->s);
+ if(err)
+ log_err("%s", err);
+ free(err);
+ }
for(r = mstate->reply_list; r; r = r->next) {
/* if a response-ip address block has been stored the
* information should be logged for each client. */
@@ -1197,6 +1213,8 @@ void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate)
mesh->mods.mod[ref->s->s.curmod]->inform_super));
(*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s,
ref->s->s.curmod, &ref->s->s);
+ /* copy state that is always relevant to super */
+ copy_state_to_super(&mstate->s, ref->s->s.curmod, &ref->s->s);
}
}