2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 05:38:06 +00:00

postfix-3.9-20240226-nonprod

This commit is contained in:
Wietse Z Venema 2024-02-26 00:00:00 -05:00 committed by Viktor Dukhovni
parent bcdad79379
commit 3f76412c48
7 changed files with 507 additions and 34 deletions

View File

@ -11,7 +11,8 @@ DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
INCL =
LIB = lib$(LIB_PREFIX)dns$(LIB_SUFFIX)
TESTPROG= test_dns_lookup dns_rr_to_pa dns_rr_to_sa dns_sa_to_rr dns_rr_eq_sa
TESTPROG= test_dns_lookup dns_rr_to_pa dns_rr_to_sa dns_sa_to_rr dns_rr_eq_sa \
dns_rr_test
LIBS = ../../lib/lib$(LIB_PREFIX)global$(LIB_SUFFIX) \
../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX)
LIB_DIR = ../../lib
@ -31,7 +32,7 @@ test: $(TESTPROG)
tests: test dns_rr_to_pa_test dns_rr_to_sa_test dns_sa_to_rr_test \
dns_rr_eq_sa_test no-a-test no-aaaa-test no-mx-test \
error-filter-test nullmx_test nxdomain_test mxonly_test \
dnsbl_tests
dnsbl_tests dns_rr_tests
dnsbl_tests: \
dnsbl_ttl_127.0.0.2_bind_plain_test \
@ -57,7 +58,7 @@ DNSBL_EXIST_REPLY_FIX = \
-e 's/ [0-9]* [0-9]* [0-9]* [0-9]* [0-9]*/ D D D D D/' \
-e 's/127.0.0.[0-9]*$$/127.0.0.D/' \
| uniq
root_tests:
$(LIB): $(OBJS)
@ -240,6 +241,12 @@ dnsbl_ttl_127.0.0.2_priv_ncache_test: test_dns_lookup dnsbl_ttl_127.0.0.2_bind_p
diff dnsbl_ttl_127.0.0.2_bind_plain.ref dnsbl_ttl_127.0.0.2_priv_ncache.tmp
rm -f dnsbl_ttl_127.0.0.2_priv_ncache.tmp
dns_rr_tests: dns_rr_test
$(SHLIB_ENV) $(VALGRIND) ./dns_rr_test
dns_rr_test: dns_rr_test.o $(LIB) $(LIBS)
$(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
@ -319,6 +326,19 @@ dns_rr_filter.o: ../../include/vstream.h
dns_rr_filter.o: ../../include/vstring.h
dns_rr_filter.o: dns.h
dns_rr_filter.o: dns_rr_filter.c
dns_rr_test.o: ../../include/check_arg.h
dns_rr_test.o: ../../include/msg.h
dns_rr_test.o: ../../include/msg_vstream.h
dns_rr_test.o: ../../include/myaddrinfo.h
dns_rr_test.o: ../../include/mymalloc.h
dns_rr_test.o: ../../include/sock_addr.h
dns_rr_test.o: ../../include/stringops.h
dns_rr_test.o: ../../include/sys_defs.h
dns_rr_test.o: ../../include/vbuf.h
dns_rr_test.o: ../../include/vstream.h
dns_rr_test.o: ../../include/vstring.h
dns_rr_test.o: dns.h
dns_rr_test.o: dns_rr_test.c
dns_rr_to_pa.o: ../../include/check_arg.h
dns_rr_to_pa.o: ../../include/msg.h
dns_rr_to_pa.o: ../../include/myaddrinfo.h

View File

@ -164,7 +164,6 @@ typedef struct DNS_RR {
struct DNS_RR *next; /* linkage */
size_t data_len; /* actual data size */
char *data; /* a bunch of data */
int len; /* list length */
int flags; /* DNS_RR_FLAG_XX, see below */
/* Add new fields at the end, for ABI forward compatibility. */
} DNS_RR;

View File

@ -97,21 +97,16 @@
/*
/* dns_rr_copy() makes a copy of a resource record.
/*
/* dns_rr_append() appends an entire input resource record
/* list to an output list, or discards the entire input list.
/* Null arguments are explicitly allowed. When the output list
/* already contains var_dns_rr_list_limit or more elements
/* dns_rr_append() appends an input resource record list to
/* an output list. Null arguments are explicitly allowed.
/* When the result would be longer than var_dns_rr_list_limit
/* (default: 100), dns_rr_append() logs a warning, flags the
/* output list as truncated, and discards the entire input
/* list. Otherwise, dns_rr_append() appends the entire input
/* list to the output list. Once an output list is flagged
/* as truncated (test with DNS_RR_IS_TRUNCATED()), the caller
/* is expected to stop trying to append records to that list.
/* Note 1: the input list is either entirely discarded or
/* entirely appended; the output list may therefore be longer
/* than var_dns_rr_list_limit. Note 2: the 'truncated' flag
/* is transitive, i.e. when appending a input list that was
/* flagged as truncated to an output list, the output list
/* output list as truncated, and discards the excess elements.
/* Once an output list is flagged as truncated (test with
/* DNS_RR_IS_TRUNCATED()), the caller is expected to stop
/* trying to append records to that list. Note: the 'truncated'
/* flag is transitive, i.e. when appending a input list that
/* was flagged as truncated to an output list, the output list
/* will also be flagged as truncated.
/*
/* dns_rr_sort() sorts a list of resource records into ascending
@ -206,7 +201,6 @@ DNS_RR *dns_rr_create(const char *qname, const char *rname,
}
rr->data_len = data_len;
rr->next = 0;
rr->len = 1;
rr->flags = 0;
return (rr);
}
@ -245,6 +239,41 @@ DNS_RR *dns_rr_copy(DNS_RR *src)
return (dst);
}
/* dns_rr_append_with_limit - append resource record to limited list */
static void dns_rr_append_with_limit(DNS_RR *list, DNS_RR *rr, int limit)
{
/*
* Pre: list != 0, all lists are concatenated with dns_rr_append().
*
* Post: all elements have the DNS_RR_FLAG_TRUNCATED flag value set, or all
* elements have it cleared, so that there is no need to update code in
* legacy stable releases that deletes or reorders elements.
*/
if (limit <= 1) {
if (list->next || rr) {
msg_warn("DNS record count limit (%d) exceeded -- dropping"
" excess record(s) after qname=%s qtype=%s",
var_dns_rr_list_limit, list->qname,
dns_strtype(list->type));
list->flags |= DNS_RR_FLAG_TRUNCATED;
dns_rr_free(list->next);
dns_rr_free(rr);
list->next = 0;
}
} else {
if (list->next == 0 && rr) {
list->next = rr;
rr = 0;
}
if (list->next) {
dns_rr_append_with_limit(list->next, rr, limit - 1);
list->flags |= list->next->flags;
}
}
}
/* dns_rr_append - append resource record(s) to list, or discard */
DNS_RR *dns_rr_append(DNS_RR *list, DNS_RR *rr)
@ -258,17 +287,9 @@ DNS_RR *dns_rr_append(DNS_RR *list, DNS_RR *rr)
return (list);
if (list == 0)
return (rr);
if (list->len < var_dns_rr_list_limit) {
list->next = dns_rr_append(list->next, rr);
/* Lengths are o(100) an are always safe to add. */
list->len += rr->len;
list->flags |= rr->flags;
if (!DNS_RR_IS_TRUNCATED(list)) {
dns_rr_append_with_limit(list, rr, var_dns_rr_list_limit);
} else {
if ((list->flags & DNS_RR_FLAG_TRUNCATED) == 0) {
msg_warn("dropping excess records for qname=%s qtype=%s",
rr->qname, dns_strtype(rr->type));
list->flags |= DNS_RR_FLAG_TRUNCATED;
}
dns_rr_free(rr);
}
return (list);

View File

@ -0,0 +1,433 @@
/*
* System library.
*/
#include <sys_defs.h>
#include <stdlib.h>
/*
* Utility library.
*/
#include <msg.h>
#include <msg_vstream.h>
#include <mymalloc.h>
#include <stringops.h>
#include <vstring.h>
/*
* DNS library.
*/
#include <dns.h>
#define STR(x) vstring_str(x)
/*
* Test helpers. TODO: move eq_dns_rr() to testing/dns_rr_testers.c; need to
* verify that the expected difference is reported, or use a GTEST matcher.
*/
/* print_dns_rr - format as { qname, reply, flags } */
static char *print_dns_rr(VSTRING *buf, DNS_RR *rr)
{
static VSTRING *tmp;
if (tmp == 0)
tmp = vstring_alloc(100);
vstring_sprintf(buf, "{qname=%s, reply='%s', flags=0x%x}",
rr->qname, dns_strrecord(tmp, rr), rr->flags);
return (STR(buf));
}
/* eq_dns_rr - predicate that two lists are equivalent */
static int eq_dns_rr(DNS_RR *got, DNS_RR *want)
{
VSTRING *got_buf = 0;
VSTRING *want_buf = 0;
#define EQ_DNS_RR_RETURN(val) do { \
if (got_buf) \
vstring_free(got_buf); \
if (want_buf) \
vstring_free(want_buf); \
return (val); \
} while (0)
/* Same length. */
if (got == 0 && want == 0)
EQ_DNS_RR_RETURN(1);
if (want == 0) {
msg_warn("got %s, want null",
print_dns_rr(got_buf = vstring_alloc(100), got));
}
if (got == 0) {
msg_warn("got null, want %s",
print_dns_rr(want_buf = vstring_alloc(100), want));
EQ_DNS_RR_RETURN(0);
}
/* Same query name, resource record, flags. */
if (strcmp(print_dns_rr(got_buf = vstring_alloc(100), got),
print_dns_rr(want_buf = vstring_alloc(100), want)) != 0) {
msg_warn("got %s, want %s", STR(want_buf), STR(got_buf));
EQ_DNS_RR_RETURN(0);
}
/* Same children. */
EQ_DNS_RR_RETURN(eq_dns_rr(got->next, want->next));
}
static int eq_dns_rr_free(DNS_RR *got, DNS_RR *want)
{
int res = eq_dns_rr(got, want);
dns_rr_free(got);
dns_rr_free(want);
return (res);
}
/*
* Tests and test cases.
*/
typedef struct TEST_CASE {
const char *label; /* identifies test case */
int (*fn) (void);
} TEST_CASE;
#define PASS (0)
#define FAIL (1)
/*
* Begin helper tests. TODO: move these to testing/dns_rr_testers_test.c.
*/
static int eq_dns_rr_qname_differ(void)
{
DNS_RR *got = dns_rr_create("qa", "ra", T_SRV, C_IN, 3600, 1, 25, 1, "mxa", 3);
DNS_RR *want = dns_rr_copy(got);
myfree(want->qname);
want->qname = mystrdup("qb");
return (!eq_dns_rr_free(got, want));
}
static int eq_dns_rr_reply_differ(void)
{
DNS_RR *got = dns_rr_create("qa", "ra", T_SRV, C_IN, 3600, 1, 25, 1, "mxa", 3);
DNS_RR *want = dns_rr_copy(got);
want->port += 1;
return (!eq_dns_rr_free(got, want));
}
/*
* End helper tests.
*/
/*
* Begin DNS_RR tests.
*/
static int eq_dns_rr_flags_differ(void)
{
DNS_RR *got = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
DNS_RR *want = dns_rr_copy(got);
want->flags |= DNS_RR_FLAG_TRUNCATED;
return (!eq_dns_rr_free(got, want));
}
static int append_to_null_from_null(void)
{
DNS_RR *got = dns_rr_append((DNS_RR *) 0, (DNS_RR *) 0);
DNS_RR *want = 0;
return (eq_dns_rr_free(got, want));
}
static int append_to_elem_from_null(void)
{
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
DNS_RR *got, *want;
got = dns_rr_append(dns_rr_copy(a), (DNS_RR *) 0);
want = a;
return (eq_dns_rr_free(got, want));
}
static int appent_to_null_from_elem(void)
{
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
DNS_RR *got, *want;
got = dns_rr_append((DNS_RR *) 0, dns_rr_copy(a));
want = a;
return (eq_dns_rr_free(got, want));
}
static int append_to_elem_from_elem(void)
{
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
DNS_RR *got, *want;
got = dns_rr_append(dns_rr_copy(a), dns_rr_copy(b));
(want = a)->next = b;
return (eq_dns_rr_free(got, want));
}
static int append_to_elem_from_list(void)
{
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
DNS_RR *got, *want;
got = dns_rr_append(dns_rr_copy(a),
dns_rr_append(dns_rr_copy(b),
dns_rr_copy(c)));
((want = a)->next = b)->next = c;
return (eq_dns_rr_free(got, want));
}
static int append_to_list_from_elem(void)
{
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
DNS_RR *got, *want;
got = dns_rr_append(dns_rr_append(dns_rr_copy(a),
dns_rr_copy(b)),
dns_rr_copy(c));
((want = a)->next = b)->next = c;
return (eq_dns_rr_free(got, want));
}
static int append_to_list_from_list(void)
{
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 3);
DNS_RR *got, *want;
got = dns_rr_append(dns_rr_append(dns_rr_copy(a),
dns_rr_copy(b)),
dns_rr_append(dns_rr_copy(c),
dns_rr_copy(d)));
(((want = a)->next = b)->next = c)->next = d;
return (eq_dns_rr_free(got, want));
}
static int append_propagates_flags(void)
{
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 3);
DNS_RR *left = dns_rr_append(dns_rr_copy(a), dns_rr_copy(b));
DNS_RR *rite = dns_rr_append(dns_rr_copy(c), dns_rr_copy(d));
DNS_RR *got, *want, *rr;
for (rr = rite; rr; rr = rr->next)
rr->flags |= DNS_RR_FLAG_TRUNCATED;
got = dns_rr_append(left, rite);
(((want = a)->next = b)->next = c)->next = d;
for (rr = want; rr; rr = rr->next)
rr->flags |= DNS_RR_FLAG_TRUNCATED;
return (eq_dns_rr_free(got, want));
}
static int append_to_list_from_list_truncate(void)
{
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 3);
DNS_RR *got, *want, *rr;
var_dns_rr_list_limit = 3;
((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c);
for (rr = want; rr; rr = rr->next)
rr->flags |= DNS_RR_FLAG_TRUNCATED;
got = dns_rr_append(dns_rr_append(a, b),
dns_rr_append(c, d));
return (eq_dns_rr_free(got, want));
}
static int append_to_list_from_elem_elem_truncate(void)
{
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 3);
DNS_RR *got, *want, *rr;
var_dns_rr_list_limit = 2;
(want = dns_rr_copy(a))->next = dns_rr_copy(b);
for (rr = want; rr; rr = rr->next)
rr->flags |= DNS_RR_FLAG_TRUNCATED;
got = dns_rr_append(a, b);
got = dns_rr_append(got, c); /* should be logged */
got = dns_rr_append(got, d); /* should be silent */
return (eq_dns_rr_free(got, want));
}
static int append_to_list_from_elem_truncate(void)
{
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
DNS_RR *got, *want, *rr;
var_dns_rr_list_limit = 2;
(want = dns_rr_copy(a))->next = dns_rr_copy(b);
for (rr = want; rr; rr = rr->next)
rr->flags |= DNS_RR_FLAG_TRUNCATED;
got = dns_rr_append(dns_rr_append(a, b), c);
return (eq_dns_rr_free(got, want));
}
static int append_to_elem_from_list_truncate(void)
{
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
DNS_RR *got, *want, *rr;
var_dns_rr_list_limit = 2;
(want = dns_rr_copy(a))->next = dns_rr_copy(b);
for (rr = want; rr; rr = rr->next)
rr->flags |= DNS_RR_FLAG_TRUNCATED;
got = dns_rr_append(a, dns_rr_append(b, c));
return (eq_dns_rr_free(got, want));
}
static int append_to_list_from_elem_exact_fit(void)
{
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
DNS_RR *got, *want;
var_dns_rr_list_limit = 3;
((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c);
got = dns_rr_append(dns_rr_append(a, b), c);
return (eq_dns_rr_free(got, want));
}
static int append_to_elem_from_list_exact_fit(void)
{
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
DNS_RR *got, *want;
var_dns_rr_list_limit = 3;
((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c);
got = dns_rr_append(a, dns_rr_append(b, c));
return (eq_dns_rr_free(got, want));
}
/*
* The test cases.
*/
static const TEST_CASE test_cases[] = {
/*
* Test eq_dns_rr; TODO: move to testing/dns_rr_testers_test.c
*/
"eq_dns_rr qname differ", eq_dns_rr_qname_differ,
"eq_dns_rr reply differ", eq_dns_rr_reply_differ,
"eq_dns_rr flags differ", eq_dns_rr_flags_differ,
/*
* Test dns_rr_append() without truncation.
*/
"append to null from null", append_to_null_from_null,
"append to null from element", appent_to_null_from_elem,
"append to element from null", append_to_elem_from_null,
"append to element from element", append_to_elem_from_elem,
"append to element from list", append_to_elem_from_list,
"append to list from element", append_to_list_from_elem,
"append to list from list", append_to_list_from_list,
/*
* Test dns_rr_append() flag propagation.
*/
"append propagates flags", append_propagates_flags,
/*
* Test dns_rr_append() with truncation.
*/
"append to list from list truncate", append_to_list_from_list_truncate,
"append to list from element element truncate", append_to_list_from_elem_elem_truncate,
"append to list from element truncate", append_to_list_from_elem_truncate,
"append to element from list truncate", append_to_elem_from_list_truncate,
"append to list from element exact fit", append_to_list_from_elem_exact_fit,
"append to element from list exact fit", append_to_elem_from_list_exact_fit,
/*
* TODO: tests dns_rr_sort(), dns_rr_srv_sort(), dns_rr_remove(),
* dns_rr_shuffle(), etc.
*/
0,
};
int main(int argc, char **argv)
{
const TEST_CASE *tp;
int pass = 0;
int fail = 0;
VSTRING *res_buf = vstring_alloc(100);
int saved_limit = var_dns_rr_list_limit;
msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);
for (tp = test_cases; tp->label != 0; tp++) {
msg_info("RUN %s", tp->label);
if (tp->fn() == 0) {
fail++;
msg_info("FAIL %s", tp->label);
} else {
msg_info("PASS %s", tp->label);
pass++;
}
var_dns_rr_list_limit = saved_limit;
}
msg_info("PASS=%d FAIL=%d", pass, fail);
vstring_free(res_buf);
exit(fail != 0);
}

View File

@ -78,11 +78,12 @@ char *dns_strrecord(VSTRING *buf, DNS_RR *rr)
vstring_sprintf_append(buf, "%s", rr->data);
break;
case T_MX:
vstring_sprintf_append(buf, "%u %s.", rr->pref, rr->data);
vstring_sprintf_append(buf, "%u %.*s.", rr->pref,
(int) rr->data_len, rr->data);
break;
case T_SRV:
vstring_sprintf_append(buf, "%u %u %u %s.", rr->pref, rr->weight,
rr->port, rr->data);
vstring_sprintf_append(buf, "%u %u %u %.*s.", rr->pref, rr->weight,
rr->port, (int) rr->data_len, rr->data);
break;
case T_TLSA:
if (rr->data_len >= 3) {

View File

@ -123,7 +123,6 @@ int main(int argc, char **argv)
if (rr) {
vstream_printf("%s: fqdn: %s\n", name, vstring_str(fqdn));
buf = vstring_alloc(100);
vstream_printf("%s: %d records\n", name, rr->len);
print_rr(buf, rr);
vstream_fflush(VSTREAM_OUT);
if (DNS_RR_IS_TRUNCATED(rr))

View File

@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
#define MAIL_RELEASE_DATE "20240223"
#define MAIL_RELEASE_DATE "20240226"
#define MAIL_VERSION_NUMBER "3.9"
#ifdef SNAPSHOT