From: Vsevolod Stakhov Date: Mon, 10 Nov 2025 09:26:25 +0000 (+0000) Subject: [Fix] Regenerate DNS transaction ID before copying packet to TCP buffer X-Git-Tag: 3.14.0~4^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c774de1a529f73d212729032ded381cc5a619359;p=thirdparty%2Frspamd.git [Fix] Regenerate DNS transaction ID before copying packet to TCP buffer When switching from UDP to TCP (e.g., on truncated response), the code was copying the packet to the TCP output buffer before regenerating the transaction ID to avoid collisions. This resulted in both UDP and TCP packets having the same transaction ID. Fix by moving the ID regeneration and IO channel switch logic before the memcpy to the TCP output buffer, ensuring the TCP packet contains the updated transaction ID. --- diff --git a/contrib/librdns/resolver.c b/contrib/librdns/resolver.c index 0613a6b4e5..5092efe6f0 100644 --- a/contrib/librdns/resolver.c +++ b/contrib/librdns/resolver.c @@ -484,19 +484,6 @@ rdns_reschedule_req_over_tcp(struct rdns_request *req, struct rdns_server *serv) return false; } - oc->write_buf = ((unsigned char *) oc) + sizeof(*oc); - memcpy(oc->write_buf, req->packet, req->pos); - oc->next_write_size = htons(req->pos); - - DL_APPEND(ioc->tcp->output_chain, oc); - - if (ioc->tcp->async_write == NULL) { - ioc->tcp->async_write = resolver->async->add_write( - resolver->async->data, - ioc->sock, ioc); - } - - req->state = RDNS_REQUEST_TCP; /* Switch IO channel from UDP to TCP */ rdns_request_remove_from_hash(req); req->io = ioc; @@ -518,6 +505,20 @@ rdns_reschedule_req_over_tcp(struct rdns_request *req, struct rdns_server *serv) } } + oc->write_buf = ((unsigned char *) oc) + sizeof(*oc); + memcpy(oc->write_buf, req->packet, req->pos); + oc->next_write_size = htons(req->pos); + + DL_APPEND(ioc->tcp->output_chain, oc); + + if (ioc->tcp->async_write == NULL) { + ioc->tcp->async_write = resolver->async->add_write( + resolver->async->data, + ioc->sock, ioc); + } + + req->state = RDNS_REQUEST_TCP; + req->async_event = resolver->async->add_timer(resolver->async->data, req->timeout, req);