- Fix to drop UDP for discard-timeout, but not stream connections.

This commit is contained in:
W.C.A. Wijngaards 2025-10-15 11:04:22 +02:00
parent a75ea01a15
commit 735c96aac7
3 changed files with 37 additions and 22 deletions

View file

@ -1,3 +1,6 @@
15 October 2025: Wouter
- Fix to drop UDP for discard-timeout, but not stream connections.
10 October 2025: Wouter
- Fix #1358 Enabling FIPS in OpenSSL causes unit test to fail.

View file

@ -496,6 +496,9 @@ These options are part of the **server:** clause.
The wait time in msec where recursion requests are dropped.
This is to stop a large number of replies from accumulating.
They receive no reply, the work item continues to recurse.
For UDP the replies are dropped, for stream connections the reply
is not dropped if the stream connection is still open ready to receive
answers.
It is nice to be a bit larger than
:ref:`serve-expired-client-timeout<unbound.conf.serve-expired-client-timeout>`
if that is enabled.

View file

@ -1728,28 +1728,37 @@ void mesh_query_done(struct mesh_state* mstate)
dns_error_reporting(&mstate->s, 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;
if(r->query_reply.c->use_h2)
http2_stream_remove_mesh_state(r->h2_stream);
comm_point_drop_reply(&r->query_reply);
mstate->reply_list = reply_list;
mstate->s.env->mesh->num_queries_discard_timeout++;
continue;
if(mesh_is_udp(r)) {
/* For UDP queries, the old replies are discarded.
* This stops a large volume of old replies from
* building up.
* The stream replies, are not discarded. The
* stream is open, the other side is waiting.
* Some answer is needed, even if servfail, but the
* real reply is ready to go, so that is given. */
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;
if(r->query_reply.c->use_h2)
http2_stream_remove_mesh_state(r->h2_stream);
comm_point_drop_reply(&r->query_reply);
mstate->reply_list = reply_list;
mstate->s.env->mesh->num_queries_discard_timeout++;
continue;
}
}
i++;