From 56b74b7ea2a7c2a20c7f6f2e308f4b350c04b128 Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Tue, 24 Mar 2026 11:43:19 +0100 Subject: [PATCH] MINOR: resolvers: basic TXT record implementation This patch adds support for TXT records. It allows to get the first string of a TXT-record which is limited to 255 characters. The rest of the record is ignored. --- include/haproxy/resolvers-t.h | 1 + src/resolvers.c | 30 +++++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/include/haproxy/resolvers-t.h b/include/haproxy/resolvers-t.h index ace35c510..e89f5b547 100644 --- a/include/haproxy/resolvers-t.h +++ b/include/haproxy/resolvers-t.h @@ -72,6 +72,7 @@ extern struct pool_head *resolv_requester_pool; /* dns record types (non exhaustive list) */ #define DNS_RTYPE_A 1 /* IPv4 address */ #define DNS_RTYPE_CNAME 5 /* canonical name */ +#define DNS_RTYPE_TXT 16 /* TXT */ #define DNS_RTYPE_AAAA 28 /* IPv6 address */ #define DNS_RTYPE_SRV 33 /* SRV record */ #define DNS_RTYPE_OPT 41 /* OPT */ diff --git a/src/resolvers.c b/src/resolvers.c index f48a2bf9b..4cc13179d 100644 --- a/src/resolvers.c +++ b/src/resolvers.c @@ -1326,15 +1326,33 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe key = XXH32(reader, answer_record->data_len, answer_record->type); break; + case DNS_RTYPE_TXT: { + /* TXT: sequence of [1-byte length | string bytes] *. + * Only the first string is kept, further data is ignored. + */ + int slen = (unsigned char)reader[0]; + + if (answer_record->data_len < 1 || 1 + slen > answer_record->data_len) + goto invalid_resp; + offset = answer_record->data_len; + memcpy(answer_record->data.target, reader + 1, slen); + answer_record->data.target[slen] = 0; + answer_record->data_len = slen; + key = XXH32(answer_record->data.target, slen, answer_record->type); + break; + } + } /* switch (record type) */ /* Increment the counter for number of records saved into our * local response */ nb_saved_records++; - /* Move forward answer_record->data_len for analyzing next - * record in the response */ - reader += ((answer_record->type == DNS_RTYPE_SRV) + /* Move forward past the record data. For SRV and TXT, offset holds + * the wire data length + */ + reader += ((answer_record->type == DNS_RTYPE_SRV || + answer_record->type == DNS_RTYPE_TXT) ? offset : answer_record->data_len); @@ -1370,6 +1388,12 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe } break; + case DNS_RTYPE_TXT: + if (answer_record->data_len == tmp_record->data_len && + memcmp(answer_record->data.target, tmp_record->data.target, answer_record->data_len) == 0) + found = 1; + break; + default: break; }