aboutsummaryrefslogtreecommitdiff
path: root/services/mesh.c
diff options
context:
space:
mode:
Diffstat (limited to 'services/mesh.c')
-rw-r--r--services/mesh.c106
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)