diff options
Diffstat (limited to 'services/mesh.c')
| -rw-r--r-- | services/mesh.c | 54 |
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); } } |
