From: W.C.A. Wijngaards Date: Wed, 20 May 2026 13:04:12 +0000 (+0200) Subject: - Fix cleaning up DoH session. The same query can be on multiple X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=08e901a1ace074af4e0350a47f611efcf40b8d69;p=thirdparty%2Funbound.git - Fix cleaning up DoH session. The same query can be on multiple streams in a session. Thanks to Qifan Zhang, Palo Alto Networks, for the report. --- diff --git a/doc/Changelog b/doc/Changelog index 10f8e0351..180f0b033 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -41,6 +41,9 @@ - Fix lame server detection, for selfpointed glue records. Thanks to Shuhan Zhang, Dan Li, and Baojun Liu from Tsinghua University for the report. + - Fix cleaning up DoH session. The same query can be on multiple + streams in a session. Thanks to Qifan Zhang, Palo Alto Networks, + for the report. 18 May 2026: Wouter - Fix for mixed class referrals, the resolver uses the query diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index 5db2b940b..9dd57999f 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -2167,7 +2167,8 @@ void tcp_req_info_clear(struct tcp_req_info* req) open = req->open_req_list; while(open) { nopen = open->next; - mesh_state_remove_reply(open->mesh, open->mesh_state, req->cp); + mesh_state_remove_reply(open->mesh, open->mesh_state, req->cp, + NULL); free(open); open = nopen; } diff --git a/services/mesh.c b/services/mesh.c index 286901047..04c799751 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -1078,14 +1078,6 @@ mesh_state_cleanup(struct mesh_state* mstate) if(!mstate->replies_sent) { struct mesh_reply* rep = mstate->reply_list; struct mesh_cb* cb; - /* One http2 stream could bring down its comm_point along with - * the other streams which could share the same query. Do all - * the http2 stream bookkeeping upfront. */ - for(; rep; rep=rep->next) { - if(rep->query_reply.c->use_h2) - http2_stream_remove_mesh_state(rep->h2_stream); - } - rep = mstate->reply_list; /* in tcp_req_info, the mstates linked are removed, but * the reply_list is now NULL, so the remove-from-empty-list * takes no time and also it does not do the mesh accounting */ @@ -2366,7 +2358,7 @@ void mesh_list_remove(struct mesh_state* m, struct mesh_state** fp, } void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m, - struct comm_point* cp) + struct comm_point* cp, struct http2_stream* h2_stream) { struct mesh_reply* n, *prev = NULL; n = m->reply_list; @@ -2374,7 +2366,8 @@ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m, * there is no accounting twice */ if(!n) return; /* nothing to remove, also no accounting needed */ while(n) { - if(n->query_reply.c == cp) { + if(n->query_reply.c == cp + && (!h2_stream || n->h2_stream == h2_stream)) { /* unlink it */ if(prev) prev->next = n->next; else m->reply_list = n->next; diff --git a/services/mesh.h b/services/mesh.h index 9ee585156..cd10bf462 100644 --- a/services/mesh.h +++ b/services/mesh.h @@ -683,9 +683,11 @@ void mesh_list_remove(struct mesh_state* m, struct mesh_state** fp, * @param mesh: to update the counters. * @param m: the mesh state. * @param cp: the comm_point to remove from the list. + * @param h2_stream: if not NULL, it specifies the h2_stream to match + * for the delete. */ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m, - struct comm_point* cp); + struct comm_point* cp, struct http2_stream* h2_stream); /** Callback for when the serve expired client timer has run out. Tries to * find an expired answer in the cache and reply that to the client. diff --git a/util/netevent.c b/util/netevent.c index a86e22518..0eb690344 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -3174,7 +3174,7 @@ static void http2_stream_delete(struct http2_session* h2_session, { if(h2_stream->mesh_state) { mesh_state_remove_reply(h2_stream->mesh, h2_stream->mesh_state, - h2_session->c); + h2_session->c, h2_stream); h2_stream->mesh_state = NULL; } http2_req_stream_clear(h2_stream);