diff options
Diffstat (limited to 'services/mesh.c')
-rw-r--r-- | services/mesh.c | 106 |
1 files changed, 100 insertions, 6 deletions
diff --git a/services/mesh.c b/services/mesh.c index 47cfb04249b5..e886c4b92c84 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -47,6 +47,7 @@ #include "services/outbound_list.h" #include "services/cache/dns.h" #include "services/cache/rrset.h" +#include "services/cache/infra.h" #include "util/log.h" #include "util/net_help.h" #include "util/module.h" @@ -385,7 +386,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) @@ -415,6 +416,14 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, if(rep->c->tcp_req_info) { r_buffer = rep->c->tcp_req_info->spool_buffer; } + if(!infra_wait_limit_allowed(mesh->env->infra_cache, rep, + edns->cookie_valid, mesh->env->cfg)) { + verbose(VERB_ALGO, "Too many queries waiting from the IP. " + "dropping incoming query."); + comm_point_drop_reply(rep); + mesh->stats_dropped++; + return; + } if(!unique) s = mesh_area_find(mesh, cinfo, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0); /* does this create a new reply state? */ @@ -511,6 +520,19 @@ 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; } +#ifdef USE_CACHEDB + 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; + } + } +#endif + infra_wait_limit_inc(mesh->env->infra_cache, rep, *mesh->env->now, + mesh->env->cfg); /* update statistics */ if(was_detached) { log_assert(mesh->num_detached_states > 0); @@ -616,6 +638,18 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, mesh_state_delete(&s->s); return 0; } +#ifdef USE_CACHEDB + 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; + } + } +#endif /* update statistics */ if(was_detached) { log_assert(mesh->num_detached_states > 0); @@ -930,6 +964,8 @@ mesh_state_cleanup(struct mesh_state* mstate) * takes no time and also it does not do the mesh accounting */ mstate->reply_list = NULL; for(; rep; rep=rep->next) { + infra_wait_limit_dec(mesh->env->infra_cache, + &rep->query_reply, mesh->env->cfg); comm_point_drop_reply(&rep->query_reply); log_assert(mesh->num_reply_addrs > 0); mesh->num_reply_addrs--; @@ -1179,7 +1215,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep, rcode = LDNS_RCODE_SERVFAIL; if(!rcode && rep && (rep->security == sec_status_bogus || rep->security == sec_status_secure_sentinel_fail)) { - if(!(reason = errinf_to_str_bogus(&m->s))) + if(!(reason = errinf_to_str_bogus(&m->s, NULL))) rcode = LDNS_RCODE_SERVFAIL; } /* send the reply */ @@ -1413,6 +1449,8 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, comm_point_send_reply(&r->query_reply); m->reply_list = rlist; } + infra_wait_limit_dec(m->s.env->infra_cache, &r->query_reply, + m->s.env->cfg); /* account */ log_assert(m->s.env->mesh->num_reply_addrs > 0); m->s.env->mesh->num_reply_addrs--; @@ -1436,7 +1474,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, log_reply_info(NO_VERBOSE, &m->s.qinfo, &r->query_reply.client_addr, r->query_reply.client_addrlen, duration, 0, r_buffer, - (m->s.env->cfg->log_destaddr?(void*)r->query_reply.c->socket->addr->ai_addr:NULL), + (m->s.env->cfg->log_destaddr?(void*)r->query_reply.c->socket->addr:NULL), r->query_reply.c->type); } } @@ -1464,12 +1502,32 @@ void mesh_query_done(struct mesh_state* mstate) && 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); + if(err) { log_err("%s", err); } } } for(r = mstate->reply_list; r; r = r->next) { + struct timeval old; + timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time); + if(mstate->s.env->cfg->discard_timeout != 0 && + ((int)old.tv_sec)*1000+((int)old.tv_usec)/1000 > + mstate->s.env->cfg->discard_timeout) { + /* Drop the reply, it is too old */ + /* briefly set the reply_list to NULL, so that the + * tcp req info cleanup routine that calls the mesh + * to deregister the meshstate for it is not done + * because the list is NULL and also accounting is not + * done there, but instead we do that here. */ + struct mesh_reply* reply_list = mstate->reply_list; + verbose(VERB_ALGO, "drop reply, it is older than discard-timeout"); + infra_wait_limit_dec(mstate->s.env->infra_cache, + &r->query_reply, mstate->s.env->cfg); + mstate->reply_list = NULL; + comm_point_drop_reply(&r->query_reply); + mstate->reply_list = reply_list; + mstate->s.env->mesh->stats_dropped++; + continue; + } + i++; tv = r->start_time; @@ -1493,6 +1551,8 @@ void mesh_query_done(struct mesh_state* mstate) * because the list is NULL and also accounting is not * done there, but instead we do that here. */ struct mesh_reply* reply_list = mstate->reply_list; + infra_wait_limit_dec(mstate->s.env->infra_cache, + &r->query_reply, mstate->s.env->cfg); mstate->reply_list = NULL; comm_point_drop_reply(&r->query_reply); mstate->reply_list = reply_list; @@ -2025,6 +2085,8 @@ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m, /* delete it, but allocated in m region */ log_assert(mesh->num_reply_addrs > 0); mesh->num_reply_addrs--; + infra_wait_limit_dec(mesh->env->infra_cache, + &n->query_reply, mesh->env->cfg); /* prev = prev; */ n = n->next; @@ -2165,6 +2227,28 @@ mesh_serve_expired_callback(void* arg) log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep); for(r = mstate->reply_list; r; r = r->next) { + struct timeval old; + timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time); + if(mstate->s.env->cfg->discard_timeout != 0 && + ((int)old.tv_sec)*1000+((int)old.tv_usec)/1000 > + mstate->s.env->cfg->discard_timeout) { + /* Drop the reply, it is too old */ + /* briefly set the reply_list to NULL, so that the + * tcp req info cleanup routine that calls the mesh + * to deregister the meshstate for it is not done + * because the list is NULL and also accounting is not + * done there, but instead we do that here. */ + struct mesh_reply* reply_list = mstate->reply_list; + verbose(VERB_ALGO, "drop reply, it is older than discard-timeout"); + infra_wait_limit_dec(mstate->s.env->infra_cache, + &r->query_reply, mstate->s.env->cfg); + mstate->reply_list = NULL; + comm_point_drop_reply(&r->query_reply); + mstate->reply_list = reply_list; + mstate->s.env->mesh->stats_dropped++; + continue; + } + i++; tv = r->start_time; @@ -2192,6 +2276,8 @@ mesh_serve_expired_callback(void* arg) r, r_buffer, prev, prev_buffer); if(r->query_reply.c->tcp_req_info) tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate); + infra_wait_limit_dec(mstate->s.env->infra_cache, + &r->query_reply, mstate->s.env->cfg); prev = r; prev_buffer = r_buffer; } @@ -2238,6 +2324,14 @@ mesh_serve_expired_callback(void* arg) } } +void +mesh_respond_serve_expired(struct mesh_state* mstate) +{ + if(!mstate->s.serve_expired_data) + mesh_serve_expired_init(mstate, -1); + mesh_serve_expired_callback(mstate); +} + int mesh_jostle_exceeded(struct mesh_area* mesh) { if(mesh->all.count < mesh->max_reply_states) |