aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-07-21 17:27:38 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-07-21 17:44:57 +0300
commit4afb0614fa25dcbe960699508c589dd077dba3d1 (patch)
tree3a71e62de78e6e5fbec1300aa00d53425ceee136
parent48c6ea21f359dd1a262c71a79726d29882530ee2 (diff)
downloadmailfromd-4afb0614fa25dcbe960699508c589dd077dba3d1.tar.gz
mailfromd-4afb0614fa25dcbe960699508c589dd077dba3d1.tar.bz2
Improve DNS interface. Number of MXs used in various operations is configurable.
* mfd/dnsbase.c (_getmx): Change prototype. Use struct mxbuf, (dns_get_mx_records): Likewise. (dns_freemx): Remove. (mxbuf_init, mxbuf_free): New functions. * mfd/dns.h (mxbuf): New struct. (mxbuf_t): Remove typedef. (mxbuf_init, mxbuf_free): New functions. (dns_get_mx_records): Change proto. (dns_freemx): Remove proto. * mfd/dnscache.c (parse_value, dns_cache_get): Change signature. All callers updated. * mfd/mailfromd.h (getmx, getmxip): Change signature. (max_callout_mx, max_match_mx): New externs. (dns_cache_get): Change signature. * mfd/main.c (max_callout_mx, max_match_mx): New globals. (mf_cfg_param): New statements "max-callout-mx" and "max-match-mx". * mfd/callout.c (callout_mx): Use new mxbuf interface. * mfd/dns.c (getmx): Change signature. Use new mxbuf interface. (getmxip): Likewise. * mfd/prog.c (mx_match): Use new mxbuf interface. Limit number of MXs by max_match_mx. * mfd/spf.c (mech_mx): Use new mxbuf interface. * mfd/builtin/dns.bi (dns_cfg_param): New statement "max-dns-reply-mx". (primitive_hasmx,getmx) (primitive_ismx): Rewrite to use new mxbuf interface. * doc/values.texi (MAX_DNS_MX, MAXMXCOUNT): New values. * doc/functions.texi: Update. * doc/mailfromd.texi: Update. * doc/pmult.texi: Update. * doc/values.texi (MAX_DNS_MX, MAXMXCOUNT): New values.
-rw-r--r--doc/functions.texi16
-rw-r--r--doc/mailfromd.texi32
-rw-r--r--doc/pmult.texi3
-rw-r--r--doc/values.texi2
-rw-r--r--mfd/builtin/dns.bi75
-rw-r--r--mfd/callout.c21
-rw-r--r--mfd/dns.c37
-rw-r--r--mfd/dns.h19
-rw-r--r--mfd/dnsbase.c48
-rw-r--r--mfd/dnscache.c10
-rw-r--r--mfd/mailfromd.h9
-rw-r--r--mfd/main.c10
-rw-r--r--mfd/prog.c16
-rw-r--r--mfd/spf.c17
14 files changed, 219 insertions, 96 deletions
diff --git a/doc/functions.texi b/doc/functions.texi
index 51b4a8ff..4e227e41 100644
--- a/doc/functions.texi
+++ b/doc/functions.texi
@@ -1444,8 +1444,10 @@ getmx("org.pl") @result{} ""
@emph{Notes}:
@enumerate 1
-@item The @code{getmx} function returns at most 32 @acronym{MX} names or @acronym{IP} addresses.
-@FIXME{This limit should be configurable.}
+@item The number of @acronym{MX} names or @acronym{IP} addresses
+returned by @code{getmx} is limited by the value of
+@code{max-dns-reply-mx} configuration statement (default
+@value{MAX_DNS_MX}). @xref{conf-runtime, max-dns-reply-mx}.
@item The number of items returned by @code{getmx(@var{domain})} can
differ from that obtained from @code{getmx(@var{domain}, 1)}, e.g.:
@@ -1541,6 +1543,10 @@ exception @code{e_not_found}.
If @acronym{DNS} query fails, the function raises @code{failure} or
@code{temp_failure}, depending on the character of the failure.
+
+ The number of @samp{MX} records examined by this function is limited
+by the value of the @code{max-dns-reply-mx} configuration statement
+(@pxref{conf-runtime, max-dns-reply-mx}.
@end deftypefn
@anchor{ismx}
@@ -1553,7 +1559,11 @@ is a host name or @acronym{IP} address.
records for the @var{domain}. Otherwise it returns @code{false}.
If @var{domain} has no @samp{MX} records, or if the @acronym{DNS} query fails, the
-function returns @code{false}.
+function returns @code{false}.
+
+ The number of @samp{MX} records examined by this function is limited
+by the value of the @code{max-dns-reply-mx} configuration statement
+(@pxref{conf-runtime, max-dns-reply-mx}.
@end deftypefn
@deftypefn {Built-in Function} string primitive_resolve (string @var{host}, @
diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi
index 57e2fbb6..74f9a5a8 100644
--- a/doc/mailfromd.texi
+++ b/doc/mailfromd.texi
@@ -309,6 +309,7 @@ Configuring @command{mailfromd}
* conf-priv:: Privilege Configuration
* conf-database:: Database Configuration
* conf-runtime:: Runtime Constants
+* conf-other:: Other Configuration Statements
* conf-mailutils:: Standard Mailutils Statements
@command{Mailfromd} Command Line Syntax
@@ -5367,7 +5368,7 @@ certain restrictions on the statements that can be used within them:
@cindex @code{return} in @samp{end}
@cindex @samp{end} and @code{return}
@item @code{return} cannot be used in @samp{begin} and @samp{end}
-handlers. @FIXME{It could be a useful feature, though.}
+handlers.
@cindex @code{accept} in @samp{begin}
@cindex @samp{begin} and @code{accept}
@@ -6071,6 +6072,7 @@ $f fnmatches "*org*" @result{} @code{true}
@end group
@end smallexample
+@anchor{mx matches}
@cindex mx matches
Both operators have a special form, for @dfn{@samp{MX} pattern matching}.
The expression:
@@ -6098,6 +6100,10 @@ returns true. Otherwise, its result is false.
returns true only if any of the @samp{MX}s for (domain or email) @var{x}
match the globbing pattern @var{y}.
+ These operators examine at most @value{MAXMXCOUNT} @samp{MX}
+records. To change this limit, use the @code{max-match-mx}
+configuration statement (@pxref{conf-other, max-match-mx}).
+
Both @code{mx matches} and @code{mx fnmatches} can signal the
following exceptions: @code{e_temp_failure}, @code{e_failure}.
@@ -7484,7 +7490,7 @@ can be used in complex scripts to create non-local exits from deeply
nested statements. @FIXME{Elaborate on that.}
Notice, that the the @var{excode} argument must be an immediate
-value: an exception identifier (either built-in one or one declared
+value: an exception identifier (either a built-in one or one declared
previously using a @code{dclex} statement).
@node Polling
@@ -8602,6 +8608,7 @@ Mailutils Manual}.
* conf-priv:: Privilege Configuration
* conf-database:: Database Configuration
* conf-runtime:: Runtime Constants
+* conf-other:: Other Configuration Statements
* conf-mailutils:: Standard Mailutils Statements
@end menu
@@ -9049,6 +9056,11 @@ setvar mailfrom_address @var{string};
@end smallexample
@end deffn
+@deffn {Mailfromd Conf} max-callout-mx number
+ Sets the maximum number of MXs to be polled during a callout
+verification. Defaults to @value{MAXMXCOUNT}.
+@end deffn
+
@node conf-priv
@section Privilege Configuration
@@ -9188,6 +9200,22 @@ returned in a reply. This affects the @code{dns_getname} function
(@pxref{DNS functions, dns_getname}). The default value is @value{MAX_DNS_PTR}.
@end deffn
+@deffn {runtime} max-dns-reply-mx number
+Sets the maximum number of @acronym{DNS} @samp{MX} records to be
+returned in a reply. This affects the following functions:
+@code{getpx}, @code{ismx}, @code{primitive_mx}
+(@pxref{DNS functions}). The default value is @value{MAX_DNS_MX}.
+@end deffn
+
+@node conf-other
+@section Other Configuration Statements
+
+@deffn {Mailfromd Conf} max-match-mx number
+Sets the maximum number of MXs to use in @samp{mx matches} operations
+(@pxref{mx matches}). Defaults to @value{MAXMXCOUNT}.
+@end deffn
+
+
@node conf-mailutils
@section Standard Mailutils Statements
diff --git a/doc/pmult.texi b/doc/pmult.texi
index bf9bfb08..4c5af1ea 100644
--- a/doc/pmult.texi
+++ b/doc/pmult.texi
@@ -161,8 +161,7 @@ always @samp{1}. Defined in @code{envfrom} and subsequent handlers.
@item nrcpts
The number of validated recipients for a single message. Defined in
-@code{envfrom} and @code{envrcpt} handlers. @FIXME{Verify if it
-matches this semantics.}
+@code{envfrom} and @code{envrcpt} handlers.
@item r
Protocol used to receive the message. The value of this macro is
diff --git a/doc/values.texi b/doc/values.texi
index 6d83ef47..c9c655d9 100644
--- a/doc/values.texi
+++ b/doc/values.texi
@@ -16,3 +16,5 @@
@set NMSGS 1024
@set MAX_DNS_A 64
@set MAX_DNS_PTR 64
+@set MAX_DNS_MX 32
+@set MAXMXCOUNT 32
diff --git a/mfd/builtin/dns.bi b/mfd/builtin/dns.bi
index 9f4eed65..6782edf9 100644
--- a/mfd/builtin/dns.bi
+++ b/mfd/builtin/dns.bi
@@ -21,11 +21,14 @@
static size_t max_ptr = 64;
static size_t max_a = 64;
+static size_t max_mx = MAXMXCOUNT;
static struct mu_cfg_param dns_cfg_param[] = {
{ "max-dns-reply-a", mu_cfg_size, &max_a, 0, NULL,
N_("Maximum number of A records in a DNS reply.") },
{ "max-dns-reply-ptr", mu_cfg_size, &max_a, 0, NULL,
N_("Maximum number of PTR records in a DNS reply.") },
+ { "max-dns-reply-mx", mu_cfg_size, &max_mx, 0, NULL,
+ N_("Maximum number of MX records in a DNS reply.") },
{ NULL }
};
@@ -173,18 +176,18 @@ END
MF_DEFUN(primitive_hasmx, NUMBER, STRING string)
{
- mxbuf_t mxbuf;
+ struct mxbuf mxbuf;
mf_status mxstat;
- mxstat = getmx(string, mxbuf);
+ mxbuf.mx_flags = 0;
+ mxstat = getmx(string, &mxbuf);
MF_ASSERT(mxstat == mf_success || mxstat == mf_not_found,
mf_status_to_exception(mxstat),
_("cannot get MX records for %s"),
string);
-
+ mxbuf_free(&mxbuf);
if (mxstat == mf_success) {
- dns_freemx(mxbuf);
MF_RETURN(1);
}
MF_RETURN(0);
@@ -196,16 +199,20 @@ MF_DEFUN(getmx, STRING, STRING domain, OPTIONAL, NUMBER no_resolve)
mf_status mxstat;
if (MF_OPTVAL(no_resolve)) {
- GACOPYZ_UINT32_T ipbuf[MAXMXCOUNT];
+ GACOPYZ_UINT32_T *ipbuf;
size_t ipcount;
-
- mxstat = getmxip(domain, ipbuf, &ipcount);
- MF_ASSERT(mxstat == mf_success || mxstat == mf_not_found,
- mf_status_to_exception(mxstat),
- _("cannot get MX records for %s"), domain);
- if (mxstat == mf_not_found)
+
+ ipbuf = xcalloc(max_mx, sizeof(ipbuf[0]));
+ mxstat = getmxip(domain, ipbuf, max_mx, &ipcount);
+ if (!mf_resolved(mxstat)) {
+ free(ipbuf);
+ MF_THROW(mf_status_to_exception(mxstat),
+ _("cannot get MX records for %s"), domain);
+ }
+ if (mxstat == mf_not_found) {
+ free(ipbuf);
MF_RETURN_STRING("");
- else {
+ } else {
int i;
MF_OBSTACK_BEGIN();
@@ -217,26 +224,35 @@ MF_DEFUN(getmx, STRING, STRING domain, OPTIONAL, NUMBER no_resolve)
MF_OBSTACK_1GROW(' ');
MF_OBSTACK_GROW(inet_ntoa(s));
}
+ free(ipbuf);
MF_OBSTACK_1GROW(0);
MF_RETURN_OBSTACK();
}
} else {
- mxbuf_t mxbuf;
-
- mxstat = getmx(domain, mxbuf);
- if (mxstat == mf_not_found)
+ struct mxbuf mxbuf;
+
+ mxbuf.mx_max = max_mx;
+ mxbuf.mx_flags = MXF_MAX;
+ mxstat = getmx(domain, &mxbuf);
+ if (!mf_resolved(mxstat)) {
+ mxbuf_free(&mxbuf);
+ MF_THROW(mf_status_to_exception(mxstat),
+ _("cannot get MX records for %s"), domain);
+ }
+ if (mxstat == mf_not_found) {
+ mxbuf_free(&mxbuf);
MF_RETURN_STRING("");
- else {
+ } else {
int i;
MF_OBSTACK_BEGIN();
- for (i = 0; i < MAXMXCOUNT && mxbuf[i]; i++) {
+ for (i = 0; i < mxbuf.mx_cnt; i++) {
if (i > 0)
MF_OBSTACK_1GROW(' ');
- MF_OBSTACK_GROW(mxbuf[i]);
+ MF_OBSTACK_GROW(mxbuf.mx_buf[i]);
}
MF_OBSTACK_1GROW(0);
- dns_freemx(mxbuf);
+ mxbuf_free(&mxbuf);
MF_RETURN_OBSTACK();
}
}
@@ -272,7 +288,7 @@ resolve_host(const char *string, unsigned long *ip)
MF_DEFUN(primitive_ismx, NUMBER, STRING domain, STRING ipstr)
{
- GACOPYZ_UINT32_T ipbuf[MAXMXCOUNT];
+ GACOPYZ_UINT32_T *ipbuf;
size_t ipcount;
mf_status mxstat;
unsigned long ip;
@@ -282,12 +298,15 @@ MF_DEFUN(primitive_ismx, NUMBER, STRING domain, STRING ipstr)
MF_ASSERT(resolve_host(ipstr, &ip) == 0, mfe_noresolve,
_("cannot resolve host name %s"), ipstr);
ip = ntohl(ip);
-
- mxstat = getmxip(domain, ipbuf, &ipcount);
-
- MF_ASSERT(mxstat == mf_success,
- mf_status_to_exception(mxstat),
- _("cannot get MXs for %s"), domain);
+
+ ipbuf = xcalloc(max_mx, sizeof(ipbuf[0]));
+ mxstat = getmxip(domain, ipbuf, max_mx, &ipcount);
+
+ if (mxstat != mx_success) {
+ free(ipbuf);
+ MF_THROW(mf_status_to_exception(mxstat),
+ _("cannot get MXs for %s"), domain);
+ }
for (i = 0; i < ipcount; i++) {
if (ipbuf[i] == ip) {
@@ -295,6 +314,8 @@ MF_DEFUN(primitive_ismx, NUMBER, STRING domain, STRING ipstr)
break;
}
}
+
+ free(ipbuf);
MF_RETURN(rc);
}
END
diff --git a/mfd/callout.c b/mfd/callout.c
index 3d701577..57d0c3a6 100644
--- a/mfd/callout.c
+++ b/mfd/callout.c
@@ -591,8 +591,12 @@ mf_status
callout_mx(struct smtp_io_data *iop, const char *hostname, int *pcount)
{
int i;
- mxbuf_t mxbuf;
- mf_status rc, mxstat = getmx(hostname, mxbuf);
+ struct mxbuf mxbuf;
+ mf_status rc, mxstat;
+
+ mxbuf.mx_max = max_callout_mx;
+ mxbuf.mx_flags = MXF_MAX;
+ mxstat = getmx(hostname, &mxbuf);
if (pcount)
*pcount = 0;
@@ -600,23 +604,20 @@ callout_mx(struct smtp_io_data *iop, const char *hostname, int *pcount)
case mf_success:
debug1(2,"Checking MX servers for %s", iop->email);
rc = mf_not_found;
- for (i = 0; i < MAXMXCOUNT && mxbuf[i]; i++) {
- rc = callout_host(iop, mxbuf[i]);
+ for (i = 0; i < mxbuf.mx_cnt; i++) {
+ rc = callout_host(iop, mxbuf.mx_buf[i]);
if (mf_resolved(rc))
break;
}
- if (pcount) {
- for (; i < MAXMXCOUNT && mxbuf[i]; i++)
- ;
- *pcount = i;
- }
- dns_freemx(mxbuf);
+ if (pcount)
+ *pcount = mxbuf.mx_cnt;
break;
default:
rc = mxstat;
break;
}
+ mxbuf_free(&mxbuf);
return rc;
}
diff --git a/mfd/dns.c b/mfd/dns.c
index 828665fc..46bdfc02 100644
--- a/mfd/dns.c
+++ b/mfd/dns.c
@@ -37,17 +37,22 @@ dns_to_mf_status(dns_status stat)
}
mf_status
-getmx(const char *host, mxbuf_t mxbuf)
+getmx(const char *host, struct mxbuf *mxbuf)
{
- mf_status rc = dns_cache_get(T_MX, host, mxbuf, MAXMXCOUNT);
+ mf_status rc;
+
+ mxbuf_init(mxbuf);
+ rc = dns_cache_get(T_MX, host, mxbuf->mx_buf, mxbuf->mx_max,
+ &mxbuf->mx_cnt);
if (!mf_resolved(rc)) {
dns_status status;
unsigned long ttl;
size_t mxcnt;
- status = dns_get_mx_records(host, 1, mxbuf, &mxcnt, &ttl);
+ status = dns_get_mx_records(host, 1, mxbuf, &ttl);
if (status == dns_success)
- dns_cache_put(T_MX, host, ttl, mxbuf, mxcnt);
+ dns_cache_put(T_MX, host, ttl,
+ mxbuf->mx_buf, mxbuf->mx_cnt);
else
dns_cache_put(T_MX, host, 0, NULL, 0);
rc = dns_to_mf_status(status);
@@ -56,36 +61,38 @@ getmx(const char *host, mxbuf_t mxbuf)
}
mf_status
-getmxip(char *host, GACOPYZ_UINT32_T ipbuf[MAXMXCOUNT], size_t *pcount)
+getmxip(char *host, GACOPYZ_UINT32_T *ipbuf, size_t mxmax, size_t *pcount)
{
- mxbuf_t mxbuf;
+ struct mxbuf mxbuf;
mf_status mxstat;
size_t ipcount;
size_t i;
- mxstat = getmx(host, mxbuf);
+ mxbuf.mx_max = mxmax;
+ mxbuf.mx_flags = MXF_MAX;
+ mxstat = getmx(host, &mxbuf);
if (mxstat != mf_success)
return mxstat;
ipcount = 0;
- for (i = 0; i < MAXMXCOUNT && mxbuf[i]; i++) {
+ for (i = 0; i < mxbuf.mx_cnt; i++) {
size_t ipn;
- mf_status stat = a_lookup(mxbuf[i],
+ mf_status stat = a_lookup(mxbuf.mx_buf[i],
ipbuf + ipcount,
- MAXMXCOUNT - ipcount,
+ mxmax - ipcount,
&ipn,
NULL, NULL, 0);
if (stat == mf_success) {
size_t n;
- for (n = 0; ipcount < MAXMXCOUNT && n < ipn;
+ for (n = 0; ipcount < mxmax && n < ipn;
n++, ipcount++)
ipbuf[ipcount] = ntohl(ipbuf[ipcount]);
- if (ipcount == MAXMXCOUNT)
+ if (ipcount == mxmax)
break;
}
}
- dns_freemx(mxbuf);
+ mxbuf_free(&mxbuf);
*pcount = ipcount;
return mf_success;
}
@@ -101,7 +108,7 @@ resolve_ipstr_domain(const char *ipstr, const char *domain, char **phbuf)
answer = xmalloc(MAXPACKET);
debug1(80,"Getting canonical name for %s", ipstr);
- status = dns_cache_get(T_PTR, ipstr, &hbuf, 1);
+ status = dns_cache_get(T_PTR, ipstr, &hbuf, 1, NULL);
if (status == mf_success) {
debug2(80, "%s resolved to %s (cached value)", ipstr, hbuf);
*phbuf = hbuf;
@@ -149,7 +156,7 @@ resolve_hostname(const char *host, char **pipbuf)
if (!answer)
answer = malloc(MAXPACKET);
debug1(80,"Getting IP address for %s", host);
- status = dns_cache_get(T_A, host, &ipbuf, 1);
+ status = dns_cache_get(T_A, host, &ipbuf, 1, NULL);
if (status == mf_success) {
debug2(80, "%s resolved to %s (cached value)", host, ipbuf);
*pipbuf = ipbuf;
diff --git a/mfd/dns.h b/mfd/dns.h
index 9ded5cef..bca7f684 100644
--- a/mfd/dns.h
+++ b/mfd/dns.h
@@ -29,8 +29,17 @@ typedef enum {
#endif
#define MAXMXCOUNT 32
-typedef char *mxbuf_t[MAXMXCOUNT];
+#define MXF_MAX 0x01
+#define MXF_REUSE 0x02
+
+struct mxbuf {
+ int mx_flags;
+ size_t mx_max;
+ char **mx_buf;
+ size_t mx_cnt;
+};
+
#define MAXCNAMEDEPTH 24 /* FIXME */
#ifdef HAVE_PTHREAD
@@ -66,10 +75,12 @@ typedef char *mxbuf_t[MAXMXCOUNT];
#define UPDATE_TTL(m, ttl) do { if ((m) > (ttl)) (m) = (ttl); } while(0)
+void mxbuf_init(struct mxbuf *mxbuf);
+void mxbuf_free(struct mxbuf *mxbuf);
+
int dns_str_is_ipv4(const char *addr);
-dns_status dns_get_mx_records(const char *host, int maxdepth, mxbuf_t mxbuf,
- size_t *mxcount, unsigned long *ttl);
-void dns_freemx(mxbuf_t mxbuf);
+dns_status dns_get_mx_records(const char *host, int maxdepth,
+ struct mxbuf *mxbuf, unsigned long *ttl);
int dns_reverse_ipstr(const char *ipstr, char *revipstr);
diff --git a/mfd/dnsbase.c b/mfd/dnsbase.c
index b2b3087b..c3f985c3 100644
--- a/mfd/dnsbase.c
+++ b/mfd/dnsbase.c
@@ -56,7 +56,7 @@ comp_pref(const void *a, const void *b)
static dns_status
_getmx(const char *host, unsigned char *answer, size_t answer_size,
- mxbuf_t mxbuf, size_t *pcount, unsigned long *pttl)
+ struct mxbuf *mxbuf, unsigned long *pttl)
{
int i, n, nmx;
struct mx_buffer mx_buffer[MAXMXCOUNT];
@@ -138,7 +138,7 @@ _getmx(const char *host, unsigned char *answer, size_t answer_size,
mx_buffer[nmx].name = strdup(tname);
debug2(20,"MX %u %s", mx_buffer[nmx].pref,
mx_buffer[nmx].name);
- if (++nmx >= MAXMXCOUNT)
+ if (++nmx >= mxbuf->mx_max)
break;
}
@@ -146,10 +146,10 @@ _getmx(const char *host, unsigned char *answer, size_t answer_size,
qsort(mx_buffer, nmx, sizeof mx_buffer[0], comp_pref);
/* Prepare return value */
- memset(mxbuf, 0, sizeof(mxbuf_t));
+ mxbuf_init(mxbuf);
for (i = 0; i < nmx; i++)
- mxbuf[i] = mx_buffer[i].name;
- *pcount = nmx;
+ mxbuf->mx_buf[i] = mx_buffer[i].name;
+ mxbuf->mx_cnt = nmx;
return dns_success;
}
@@ -181,8 +181,8 @@ MUTEX_DCL(dns_mutex)
to its parent domains until any record is found or recursion depth reaches
MAXDEPTH */
dns_status
-dns_get_mx_records(const char *host, int maxdepth, mxbuf_t mxbuf,
- size_t *mxcount, unsigned long *ttl)
+dns_get_mx_records(const char *host, int maxdepth, struct mxbuf *mxbuf,
+ unsigned long *ttl)
{
char *hbuf = NULL;
dns_status status = dns_failure;
@@ -207,7 +207,7 @@ dns_get_mx_records(const char *host, int maxdepth, mxbuf_t mxbuf,
if (ttl)
*ttl = ~(unsigned long)0;
status = _getmx(p, answer, MAXPACKET, mxbuf,
- mxcount, ttl);
+ ttl);
if (status == dns_success
|| status == dns_temp_failure)
break;
@@ -224,11 +224,35 @@ dns_get_mx_records(const char *host, int maxdepth, mxbuf_t mxbuf,
}
void
-dns_freemx(mxbuf_t mxbuf)
+mxbuf_init(struct mxbuf *mxbuf)
{
- int i;
- for (i = 0; i < MAXMXCOUNT && mxbuf[i]; i++)
- free(mxbuf[i]);
+ if (!(mxbuf->mx_flags & MXF_MAX))
+ mxbuf->mx_max = MAXMXCOUNT;
+ if (mxbuf->mx_flags & MXF_REUSE) {
+ int i;
+
+ for (i = 0; i < mxbuf->mx_max && mxbuf->mx_buf[i]; i++) {
+ free(mxbuf->mx_buf[i]);
+ mxbuf->mx_buf[i] = NULL;
+ }
+ } else {
+ mxbuf->mx_buf = xcalloc(mxbuf->mx_max,
+ sizeof(mxbuf->mx_buf[0]));
+ mxbuf->mx_flags |= MXF_REUSE;
+ }
+ mxbuf->mx_cnt = 0;
+}
+
+void
+mxbuf_free(struct mxbuf *mxbuf)
+{
+ if (mxbuf->mx_flags & MXF_REUSE) {
+ int i;
+
+ for (i = 0; i < mxbuf->mx_max && mxbuf->mx_buf[i]; i++)
+ free(mxbuf->mx_buf[i]);
+ mxbuf->mx_buf = NULL;
+ }
}
#define LOOKUP_FAILURE -1
diff --git a/mfd/dnscache.c b/mfd/dnscache.c
index ff1a1c25..47c72684 100644
--- a/mfd/dnscache.c
+++ b/mfd/dnscache.c
@@ -32,7 +32,7 @@
static mf_status
parse_value(int qtype, const char *keystr,
- int argc, char **argv, char **rbuf, size_t rcnt)
+ int argc, char **argv, char **rbuf, size_t rcnt, size_t *pcnt)
{
size_t i;
char *p;
@@ -56,6 +56,8 @@ parse_value(int qtype, const char *keystr,
rbuf[i] = argv[i + 1];
argv[i + 1] = NULL;
}
+ if (pcnt)
+ *pcnt = i;
for (; i < rcnt; i++)
rbuf[i] = NULL;
return mf_success;
@@ -101,7 +103,8 @@ dns_free_key(DBM_DATUM *key)
}
mf_status
-dns_cache_get(int type, const char *keystr, char **rbuf, size_t rcnt)
+dns_cache_get(int type, const char *keystr, char **rbuf, size_t rcnt,
+ size_t *pcnt)
{
mf_status rc;
DBM_FILE db;
@@ -140,7 +143,8 @@ dns_cache_get(int type, const char *keystr, char **rbuf, size_t rcnt)
mu_strerror(rc));
rc = mf_failure;
} else
- rc = parse_value(type, keystr, argc, argv, rbuf, rcnt);
+ rc = parse_value(type, keystr, argc, argv, rbuf, rcnt,
+ pcnt);
mu_argcv_free(argc, argv);
mu_dbm_datum_free(&contents);
} else {
diff --git a/mfd/mailfromd.h b/mfd/mailfromd.h
index 648a57d7..e3adbffe 100644
--- a/mfd/mailfromd.h
+++ b/mfd/mailfromd.h
@@ -150,8 +150,8 @@ mf_status resolve_ipstr_domain(const char *ipstr, const char *domain,
char **phbuf);
mf_status resolve_hostname(const char *host, char **pipbuf);
-mf_status getmx(const char *ipstr, mxbuf_t mxbuf);
-mf_status getmxip(char *host, GACOPYZ_UINT32_T ipbuf[MAXMXCOUNT],
+mf_status getmx(const char *ipstr, struct mxbuf *mxbuf);
+mf_status getmxip(char *host, GACOPYZ_UINT32_T *ipbuf, size_t ipmax,
size_t *pcount);
@@ -244,6 +244,9 @@ enum stack_expand_policy {
};
extern enum stack_expand_policy stack_expand_policy;
+extern size_t max_callout_mx;
+extern size_t max_match_mx;
+
/* Filter script parser */
@@ -1054,7 +1057,7 @@ mf_status cache_get2(const char *email, const char *client_addr);
void cache_insert2(const char *email, const char *client_addr, mf_status rc);
mf_status dns_cache_get(int type, const char *keystr, char **rbuf,
- size_t rcnt);
+ size_t rcnt, size_t *pcnt);
void dns_cache_put(int type, const char *keystr, time_t ttl, char **rbuf,
size_t rcnt);
diff --git a/mfd/main.c b/mfd/main.c
index 1211965a..4a6bbba5 100644
--- a/mfd/main.c
+++ b/mfd/main.c
@@ -111,6 +111,9 @@ int stack_trace_option; /* Print stack traces on runtime errors */
char *file_option; /* File name for DB management commands */
struct db_format *format_option;
+size_t max_callout_mx = MAXMXCOUNT;
+size_t max_match_mx = MAXMXCOUNT;
+
/* Timeouts */
time_t smtp_timeout_soft[SMTP_NUM_TIMEOUT] = {
10,
@@ -2299,12 +2302,19 @@ struct mu_cfg_param mf_cfg_param[] = {
{ "database", mu_cfg_section, NULL },
+ { "max-callout-mx", mu_cfg_size, &max_callout_mx, 0, NULL,
+ N_("Maximum number of MXs to be polled during "
+ "callout verification.") },
+
{ "callout-url", mu_cfg_callback,
NULL, 0,
cb_callout_url,
N_("URL of the callout server"),
N_("url") },
+ { "max-match-mx", mu_cfg_size, &max_match_mx, 0, NULL,
+ N_("Maximum number of MXs used by MFL \"mx match\" operation.") },
+
{ "runtime", mu_cfg_section, NULL },
{ NULL }
diff --git a/mfd/prog.c b/mfd/prog.c
index 07645b43..f1b2a6c2 100644
--- a/mfd/prog.c
+++ b/mfd/prog.c
@@ -1391,7 +1391,7 @@ mx_match(eval_environ_t env, char *string,
int (*matcher)(const char *name, void *data), void *data)
{
int rc = 0;
- mxbuf_t mxbuf;
+ struct mxbuf mxbuf;
mf_status mxstat;
char *p = strchr(string, '@');
@@ -1399,19 +1399,23 @@ mx_match(eval_environ_t env, char *string,
p++;
else
p = string;
- mxstat = getmx(p, mxbuf);
+ mxbuf.mx_max = max_match_mx;
+ mxbuf.mx_flags = MXF_MAX;
+ mxstat = getmx(p, &mxbuf);
rc = 0;
if (mxstat == mf_success) {
int i;
- for (i = 0; i < MAXMXCOUNT && mxbuf[i]; i++) {
- if (matcher(mxbuf[i], data)) {
+ for (i = 0; i < mxbuf.mx_cnt; i++) {
+ if (matcher(mxbuf.mx_buf[i], data)) {
rc = 1;
break;
}
}
- dns_freemx(mxbuf);
- } else if (mxstat != mf_not_found)
+ }
+ mxbuf_free(&mxbuf);
+
+ if (!mf_resolved(mxstat))
env_throw(env, mxstat, "cannot get MXs for %s", p);
return rc;
}
diff --git a/mfd/spf.c b/mfd/spf.c
index 03e431a0..5ff30091 100644
--- a/mfd/spf.c
+++ b/mfd/spf.c
@@ -643,8 +643,8 @@ static spf_term_result
mech_mx(spf_data *dat, spf_term_arg *arg, unsigned long masklen)
{
unsigned long netmask = make_netmask(masklen);
- mxbuf_t mxbuf;
- size_t i, mxcount;
+ struct mxbuf mxbuf;
+ size_t i;
spf_term_result result = spf_term_nomatch;
const char *domain_spec;
unsigned long ttl;
@@ -657,18 +657,17 @@ mech_mx(spf_data *dat, spf_term_arg *arg, unsigned long masklen)
debug2(2, "MX domain_spec=%s, netmask=%x",
domain_spec, netmask);
- DNS_CATCH(dns_get_mx_records(domain_spec, 1, mxbuf, &mxcount, &ttl));
+ mxbuf.mx_flags = MXF_MAX;
+ mxbuf.mx_max = 10;
+ DNS_CATCH(dns_get_mx_records(domain_spec, 1, &mxbuf, &ttl));
UPDATE_TTL(dat->ttl, ttl);
- if (mxcount > 10)
- mxcount = 10;
-
- for (i = 0; i < mxcount; i++) {
+ for (i = 0; i < mxbuf.mx_cnt; i++) {
spf_term_arg targ;
spf_term_result res;
targ.type = spf_arg_domain_spec;
- targ.v.domain_spec = mxbuf[i];
+ targ.v.domain_spec = mxbuf.mx_buf[i];
res = mech_a(dat, &targ, masklen);
if (res == spf_term_match) {
result = res;
@@ -676,7 +675,7 @@ mech_mx(spf_data *dat, spf_term_arg *arg, unsigned long masklen)
}
}
- dns_freemx(mxbuf);
+ mxbuf_free(&mxbuf);
return result;
}

Return to:

Send suggestions and report system problems to the System administrator.