]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix to drop UDP for discard-timeout, but not stream connections.
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 15 Oct 2025 09:04:22 +0000 (11:04 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 15 Oct 2025 09:04:22 +0000 (11:04 +0200)
doc/Changelog
doc/unbound.conf.rst
services/mesh.c

index 9e7bd33231d7b4a2acf68e37cf9294052809f52c..7913a457baad35919685af97049cc4d1bc2f4594 100644 (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.
 
index ec40136e04e4089459279ebbb170c5c079025be1..4c85f5a04a115768f952be85ec9538f04277a414 100644 (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.
index 40e68b70fdeab084637a46c85dc1568cc82e65fd..e78dc5e4226728b25c8d68213dfdb28e1cd4dea9 100644 (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++;