]> git.kaiwu.me - haproxy.git/commitdiff
CLEANUP: dns: use a single maximum DNS message size
authorManu Nicolas <e.nicolas@criteo.com>
Wed, 2 Sep 2026 10:08:45 +0000 (10:08 +0000)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 2 Sep 2026 11:40:00 +0000 (13:40 +0200)
The DNS code defines separate maximum message sizes for datagram and
stream processing, but both are the DNS protocol limit of 65535 bytes.
The duplicate names make common response buffers look
transport-specific and could allow the values to diverge.

The request ring size also has a TCP-specific name even though both
datagram and stream servers use it.

Replace the message limits with DNS_MAX_MSG_SIZE and rename the ring
limit to DNS_MSG_RING_MAX_SIZE. This does not change any limit or
runtime behavior.

include/haproxy/dns-t.h
include/haproxy/resolvers-t.h
src/dns.c
src/resolvers.c

index 10175cfdf0ae2423a1056c201e08a85d532b997b..5f114e146f232061987ec6d1b10f30409ea9202b 100644 (file)
@@ -39,8 +39,8 @@
 /* max pending requests per stream */
 #define DNS_STREAM_MAX_PIPELINED_REQ   4
 
-#define DNS_TCP_MSG_MAX_SIZE 65535
-#define DNS_TCP_MSG_RING_MAX_SIZE (1 + 1 + 3 + DNS_TCP_MSG_MAX_SIZE) // varint_bytes(DNS_TCP_MSG_MAX_SIZE) == 3
+#define DNS_MAX_MSG_SIZE 65535
+#define DNS_MSG_RING_MAX_SIZE (1 + 1 + 3 + DNS_MAX_MSG_SIZE) // varint_bytes(DNS_MAX_MSG_SIZE) == 3
 
 /* threshold to consider that the link to dns server is failing
  * and we should stop creating new sessions
index f0c92084c236469f65281279841e456664a4f496..4b7213a0a52ed8dcbcc55f1d21fc09cb0720832b 100644 (file)
@@ -40,7 +40,6 @@ extern struct pool_head *resolv_requester_pool;
  */
 #define DNS_MAX_LABEL_SIZE   63
 #define DNS_MAX_NAME_SIZE    255
-#define DNS_MAX_UDP_MESSAGE  65535
 
 /* DNS minimum record size: 1 char + 1 NULL + type + class */
 #define DNS_MIN_RECORD_SIZE  (1 + 1 + 2 + 2)
@@ -53,13 +52,13 @@ extern struct pool_head *resolv_requester_pool;
 #define DNS_MAX_QUERY_RECORDS 1
 
 /* maximum number of answer record in a DNS response */
-#define DNS_MAX_ANSWER_RECORDS ((DNS_MAX_UDP_MESSAGE - DNS_HEADER_SIZE) / DNS_MIN_RECORD_SIZE)
+#define DNS_MAX_ANSWER_RECORDS ((DNS_MAX_MSG_SIZE - DNS_HEADER_SIZE) / DNS_MIN_RECORD_SIZE)
 
 /* size of dns_buffer used to store responses from the buffer
  * dns_buffer is used to store data collected from records found in a response.
  * Before using it, caller will always check that there is at least DNS_MAX_NAME_SIZE bytes
  * available */
-#define DNS_ANALYZE_BUFFER_SIZE DNS_MAX_UDP_MESSAGE + DNS_MAX_NAME_SIZE
+#define DNS_ANALYZE_BUFFER_SIZE (DNS_MAX_MSG_SIZE + DNS_MAX_NAME_SIZE)
 
 /* DNS error messages */
 #define DNS_TOO_LONG_FQDN       "hostname too long"
index 53e71de0ec375f7a1bdbb77a411f156f3d97c284..9418226d529056b4b9ff1be25410cd598f087902 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
@@ -41,7 +41,7 @@ static THREAD_LOCAL char *dns_msg_trash;
 
 DECLARE_STATIC_TYPED_POOL(dns_session_pool, "dns_session", struct dns_session);
 DECLARE_STATIC_TYPED_POOL(dns_query_pool, "dns_query", struct dns_query);
-DECLARE_STATIC_POOL(dns_msg_buf, "dns_msg_buf", DNS_TCP_MSG_RING_MAX_SIZE);
+DECLARE_STATIC_POOL(dns_msg_buf, "dns_msg_buf", DNS_MSG_RING_MAX_SIZE);
 
 /* Opens an UDP socket on the namesaver's IP/Port, if required. Returns 0 on
  * success, -1 otherwise. ns->dgram must be defined.
@@ -171,7 +171,7 @@ int dns_send_nameserver(struct dns_nameserver *ns, void *buf, size_t len)
                                struct ist myist;
 
                                myist = ist2(buf, len);
-                               ret = dns_ring_write(ns->dgram->ring_req, DNS_TCP_MSG_MAX_SIZE, NULL, 0, &myist, 1);
+                               ret = dns_ring_write(ns->dgram->ring_req, DNS_MAX_MSG_SIZE, NULL, 0, &myist, 1);
                                if (!ret) {
                                        ns->counters->snd_error++;
                                        HA_SPIN_UNLOCK(DNS_LOCK, &dgram->lock);
@@ -194,7 +194,7 @@ int dns_send_nameserver(struct dns_nameserver *ns, void *buf, size_t len)
                struct ist myist;
 
                myist = ist2(buf, len);
-               ret = dns_ring_write(ns->stream->ring_req, DNS_TCP_MSG_MAX_SIZE, NULL, 0, &myist, 1);
+               ret = dns_ring_write(ns->stream->ring_req, DNS_MAX_MSG_SIZE, NULL, 0, &myist, 1);
                if (!ret) {
                        ns->counters->snd_error++;
                        return -1;
@@ -420,7 +420,7 @@ static void dns_resolve_send(struct dgram_conn *dgram)
                        break;
                cnt += len;
                BUG_ON(msg_len + ofs + cnt + 1 > b_data(buf));
-               if (unlikely(msg_len > DNS_TCP_MSG_MAX_SIZE)) {
+               if (unlikely(msg_len > DNS_MAX_MSG_SIZE)) {
                        /* too large a message to ever fit, let's skip it */
                        ofs += cnt + msg_len;
                        continue;
@@ -477,7 +477,7 @@ int dns_dgram_init(struct dns_nameserver *ns, struct sockaddr_storage *sk)
        HA_SPIN_INIT(&dgram->conn.lock);
 
        dgram->ofs_req = ~0; /* init ring offset */
-       dgram->ring_req = dns_ring_new(2*DNS_TCP_MSG_RING_MAX_SIZE);
+       dgram->ring_req = dns_ring_new(2*DNS_MSG_RING_MAX_SIZE);
        if (!dgram->ring_req) {
                ha_alert("memory allocation error initializing the ring for nameserver.\n");
                goto out;
@@ -1166,7 +1166,7 @@ struct dns_session *dns_session_new(struct dns_stream_server *dss)
        if (!ds->tx_ring_area)
                goto error;
 
-       dns_ring_init(&ds->ring, ds->tx_ring_area, DNS_TCP_MSG_RING_MAX_SIZE);
+       dns_ring_init(&ds->ring, ds->tx_ring_area, DNS_MSG_RING_MAX_SIZE);
        /* never fail because it is the first watcher attached to the ring */
        DISGUISE(dns_ring_attach(&ds->ring));
 
@@ -1244,7 +1244,7 @@ static struct task *dns_process_req(struct task *t, void *context, unsigned int
                        break;
                cnt += len;
                BUG_ON(msg_len + ofs + cnt + 1 > b_data(buf));
-               if (unlikely(msg_len > DNS_TCP_MSG_MAX_SIZE)) {
+               if (unlikely(msg_len > DNS_MAX_MSG_SIZE)) {
                        /* too large a message to ever fit, let's skip it */
                        ofs += cnt + msg_len;
                        continue;
@@ -1259,7 +1259,7 @@ static struct task *dns_process_req(struct task *t, void *context, unsigned int
                if (!LIST_ISEMPTY(&dss->free_sess)) {
                        ds = LIST_NEXT(&dss->free_sess, struct dns_session *, list);
 
-                       if (dns_ring_write(&ds->ring, DNS_TCP_MSG_MAX_SIZE, NULL, 0, &myist, 1) > 0) {
+                       if (dns_ring_write(&ds->ring, DNS_MAX_MSG_SIZE, NULL, 0, &myist, 1) > 0) {
                                ds->nb_queries++;
                                if (ds->nb_queries >= DNS_STREAM_MAX_PIPELINED_REQ)
                                        LIST_DEL_INIT(&ds->list);
@@ -1280,7 +1280,7 @@ static struct task *dns_process_req(struct task *t, void *context, unsigned int
                                ds = LIST_NEXT(&dss->idle_sess, struct dns_session *, list);
 
                                /* ring is empty so this dns_ring_write should never fail */
-                               dns_ring_write(&ds->ring, DNS_TCP_MSG_MAX_SIZE, NULL, 0, &myist, 1);
+                               dns_ring_write(&ds->ring, DNS_MAX_MSG_SIZE, NULL, 0, &myist, 1);
                                ds->nb_queries++;
                                LIST_DEL_INIT(&ds->list);
 
@@ -1305,7 +1305,7 @@ static struct task *dns_process_req(struct task *t, void *context, unsigned int
                        ads = dns_session_new(dss);
                        if (ads) {
                                /* ring is empty so this dns_ring_write should never fail */
-                               dns_ring_write(&ads->ring, DNS_TCP_MSG_MAX_SIZE, NULL, 0, &myist, 1);
+                               dns_ring_write(&ads->ring, DNS_MAX_MSG_SIZE, NULL, 0, &myist, 1);
                                ads->nb_queries++;
                                LIST_INSERT(&dss->free_sess, &ads->list);
                        }
@@ -1356,7 +1356,7 @@ int dns_stream_init(struct dns_nameserver *ns, struct server *srv)
        dss->maxconn = srv->maxconn;
 
        dss->ofs_req = ~0; /* init ring offset */
-       dss->ring_req = dns_ring_new(2*DNS_TCP_MSG_RING_MAX_SIZE);
+       dss->ring_req = dns_ring_new(2*DNS_MSG_RING_MAX_SIZE);
        if (!dss->ring_req) {
                ha_alert("memory allocation error initializing the ring for dns tcp server '%s'.\n", srv->id);
                goto out;
@@ -1438,7 +1438,7 @@ void dns_nameserver_deinit(struct dns_nameserver *ns)
 
 int init_dns_buffers()
 {
-       dns_msg_trash = malloc(DNS_TCP_MSG_MAX_SIZE);
+       dns_msg_trash = malloc(DNS_MAX_MSG_SIZE);
        if (!dns_msg_trash)
                return 0;
 
index 0dc4787bf46dfbd94fcd736725d849d1ca723c27..8c2ebe4b89127d39d28c3642531016df96c3651a 100644 (file)
@@ -2325,7 +2325,7 @@ static int resolv_process_responses(struct dns_nameserver *ns)
        struct dns_counters   *tmpcounters;
        struct resolvers  *resolvers;
        struct resolv_resolution *res;
-       unsigned char  buf[DNS_MAX_UDP_MESSAGE + 1];
+       unsigned char  buf[DNS_MAX_MSG_SIZE + 1];
        unsigned char *bufend;
        int buflen, dns_resp;
        int max_answer_records;
@@ -3923,9 +3923,9 @@ int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
                }
 
                i = atoi(args[1]);
-               if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
+               if (i < DNS_HEADER_SIZE || i > DNS_MAX_MSG_SIZE) {
                        ha_alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
-                                file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
+                                file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_MSG_SIZE, args[1]);
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
                }