]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Regenerate DNS transaction ID before copying packet to TCP buffer 5739/head
authorVsevolod Stakhov <vsevolod@rspamd.com>
Mon, 10 Nov 2025 09:26:25 +0000 (09:26 +0000)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Mon, 10 Nov 2025 09:38:35 +0000 (09:38 +0000)
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.

contrib/librdns/resolver.c

index 0613a6b4e5cb49591d62c68679c4d81522c6b077..5092efe6f09084eae134ffe32a41edf6d69a128f 100644 (file)
@@ -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);