aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS19
-rw-r--r--configure.ac2
-rw-r--r--doc/calloutd.texi1
-rw-r--r--doc/functions.texi22
-rw-r--r--doc/mailfromd.texi89
-rw-r--r--doc/upgrade.texi23
-rw-r--r--lib/dns.c363
-rw-r--r--lib/dns.h42
-rw-r--r--lib/libmf.h2
-rw-r--r--src/builtin/dns.bi90
-rw-r--r--src/callout.c2
-rw-r--r--src/mailfromd.h3
-rw-r--r--src/main.c5
-rw-r--r--src/prog.c2
-rw-r--r--src/spf.c78
-rw-r--r--src/spf.h3
-rw-r--r--src/srvcfg.c5
17 files changed, 348 insertions, 403 deletions
diff --git a/NEWS b/NEWS
index c372865b..9e7a8d7c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,13 +1,30 @@
-Mailfromd NEWS -- history of user-visible changes. 2017-10-18
+Mailfromd NEWS -- history of user-visible changes. 2017-10-19
Copyright (C) 2005-2017 Sergey Poznyakoff
See the end of file for copying conditions.
Please send Mailfromd bug reports to <bug-mailfromd@gnu.org.ua>
+Version 8.2.90
+
+* Removed arbitrary limits on the sizes of DNS RRs
+
+The following configuration statements are removed:
+
+** runtime.max-dns-reply-a
+
+** runtime.max-dns-reply-ptr
+
+** runtime.max-dns-reply-mx
+
+** max-match-mx
+
+** max-callout-mx
+
+
Version 8.2, 2017-10-18
The purpose of this release is to simplify packaging with alpha
version of Mailutils
* Requires Mailutils 3.1.92 or newer
diff --git a/configure.ac b/configure.ac
index 53e87421..2dd23baa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -14,13 +14,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AC_PREREQ(2.63)
m4_define([MF_VERSION_MAJOR], 8)
m4_define([MF_VERSION_MINOR], 2)
-dnl m4_define([MF_VERSION_PATCH], 0)
+m4_define([MF_VERSION_PATCH], 90)
AC_INIT([mailfromd],
MF_VERSION_MAJOR.MF_VERSION_MINOR[]m4_ifdef([MF_VERSION_PATCH],.MF_VERSION_PATCH),
[bug-mailfromd@gnu.org.ua],
[mailfromd],
[http://www.gnu.org.ua/software/mailfromd])
AC_CONFIG_SRCDIR([src/mailfromd.h])
diff --git a/doc/calloutd.texi b/doc/calloutd.texi
index 87f5d621..5bd91916 100644
--- a/doc/calloutd.texi
+++ b/doc/calloutd.texi
@@ -78,13 +78,12 @@ mailutils, GNU Mailutils Manual}.
@item @code{logger} @tab @xref{conf-calloutd-log}.
@item @code{logging} @tab @xref{logging statement, Mailutils Configuration File,,
mailutils, GNU Mailutils Manual}.
@item @code{mailer} @tab @xref{mailer statement, Mailutils Configuration File,,
mailutils, GNU Mailutils Manual}.
@item @code{mail-from-address} @tab @xref{conf-callout, mail-from-address}.
-@item @code{max-callout-mx} @tab @xref{conf-callout, max-callout-mx}.
@item @code{pidfile} @tab @xref{conf-calloutd-setup, pidfile}.
@item @code{server} @tab @xref{conf-calloutd-server}.
@item @code{source-ip} @tab @xref{conf-calloutd-setup, source-ip}.
@item @code{smtp-timeout} @tab @xref{conf-timeout}.
@item @code{state-directory} @tab @xref{conf-calloutd-setup, state-directory}.
@item @code{transcript} @tab @xref{conf-calloutd-log},
diff --git a/doc/functions.texi b/doc/functions.texi
index b5a33c7e..a9fb3e36 100644
--- a/doc/functions.texi
+++ b/doc/functions.texi
@@ -1917,24 +1917,20 @@ available after requesting the @file{dns} module (@pxref{Modules}):
@smallexample
require dns
@end smallexample
@deftypefn {Built-in Function} string dns_getaddr (string @var{domain})
Returns a whitespace-separated list of @acronym{IP} addresses (@code{A}
-records) for @var{domain}. At most @value{MAX_DNS_A} addresses are
-returned. @xref{conf-runtime, max-dns-reply-a}, for a description of how
-to change this limit.
+records) for @var{domain}.
This function does not use the @acronym{DNS} cache.
@end deftypefn
@deftypefn {Built-in Function} string dns_getname (string @var{ipstr})
Returns a whitespace-separated list of domain names (@code{PTR}
-records) for the @acronym{IP}v4 address @var{ipstr}. At most
-@value{MAX_DNS_PTR} names are returned. @xref{conf-runtime,
-max-dns-reply-ptr}, for a description of how to change this limit.
+records) for the @acronym{IP}v4 address @var{ipstr}.
This function does not use the @acronym{DNS} cache.
@end deftypefn
@deftypefn {Built-in Function} string getmx (string @var{domain} @
[, number @var{ip}])
@@ -1952,18 +1948,14 @@ Examples:
getmx("mafra.cz") @result{} "smtp1.mafra.cz smtp2.mafra.cz relay.iol.cz"
getmx("idnes.cz") @result{} "smtp1.mafra.cz smtp2.mafra.cz relay.iol.cz"
getmx("gnu.org") @result{} "mx10.gnu.org mx20.gnu.org"
getmx("org.pl") @result{} ""
@end smallexample
-@emph{Notes}:
+@emph{Note}:
@enumerate 1
-@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.:
@smallexample
@group
@@ -2053,16 +2045,12 @@ records for the @var{domain}.
If @var{domain} has no @samp{MX} records, @code{primitive_ismx} raises
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}
@deftypefn {Library Function} boolean ismx (string @var{domain}, @
string @var{host})
The @var{domain} argument is any valid domain name, the @var{host}
@@ -2070,16 +2058,12 @@ is a host name or @acronym{IP} address.
The function returns @code{true} if @var{host} is one of the @samp{MX}
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}.
-
- 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}, @
[string @var{domain}])
Reverse of @code{primitive_hostname}. The @code{primitive_resolve} function
returns the @acronym{IP} address for the host name specified by @var{host}
diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi
index 05c9e839..d28915f9 100644
--- a/doc/mailfromd.texi
+++ b/doc/mailfromd.texi
@@ -336,13 +336,12 @@ Configuring @command{mailfromd}
* conf-debug:: Logging and Debugging configuration
* conf-timeout:: Timeout Configuration
* conf-callout:: Call-out Configuration
* 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
* options:: Command Line Options.
* Starting and Stopping:: How to Start and Shut Down the Daemon.
@@ -468,44 +467,44 @@ appeared soon afterward. Back then it was a simple implementation of
Sender Address Verification (@pxref{SAV}) for @samp{Sendmail} (hence
its name -- @command{mailfromd}) with rudimentary tuning
possibilities.
After a short run on my mail servers, I discovered that the utility
was not flexible enough. It took less than a month to implement a
-configuration file that allowed to control program and data flow
+configuration file that allowed the user to control program and data flow
during the @samp{envfrom} @acronym{SMTP} state. The new version, 1.0,
appeared in June, 2005.
- The next major release, 1.2 (1.1 contained mostly bugfixes),
-appeared two months later, which introduced @dfn{mail sending rate}
+ Next major release, 1.2 (1.1 contained mostly bugfixes),
+appeared two months later, and introduced @dfn{mail sending rate}
control (@pxref{Rate Limit}).
- The program evolved during the next year, which led to the
-release of version 2.0 in September, 2006. This version was a major
-change in the main idea of the program. Configuration file become a
-flexible filter script allowing to control almost all @acronym{SMTP}
-states. The program supplied in the script file
-was compiled into a pseudo-code at startup, this code being subsequently
-evaluated each time the filter was invoked. This caused a considerable
-speed-up in comparison with the previous versions, where the run-time
-evaluator was traversing the parse tree. This version also introduced
-(implicitly, at the time), two separate data types for the entities
-declared in the script, which also played its role in the speed
-improvement (in the previous versions all data were considered
-strings). Lots of improvements were made in the filter language
-(@acronym{MFL}, @pxref{MFL}) itself, such as user-defined functions,
-@code{switch} statement, @code{catch} statement that allows to handle
-run-time errors, etc. The set of built-in functions extended
-considerably. A testsuite (using @i{DejaGNU}) was introduced in this version.
+ The program evolved during the next year, and the version 2.0 was
+released in September, 2006. This version was a major change in the
+main idea of the program. Configuration file become a flexible filter
+script allowing the operator to control almost all @acronym{SMTP} states. The
+program supplied in the script file was compiled into a pseudo-code at
+startup, this code being subsequently evaluated each time the filter
+was invoked. This caused a considerable speed-up in comparison with
+the previous versions, where the run-time evaluator was traversing the
+parse tree. This version also introduced (implicitly, at the time),
+two separate data types for the entities declared in the script, which
+also played its role in the speed improvement (in the previous
+versions all data were considered strings). Lots of improvements were
+made in the filter language (@acronym{MFL}, @pxref{MFL}) itself, such
+as user-defined functions, the @code{switch} statement, the @code{catch}
+statement for handling run-time errors, etc. The set of
+built-in functions extended considerably. A testsuite (using
+@i{DejaGNU}) was introduced in this version.
During this initial development period the limitations
imposed by @command{libmilter} implementation became obvious. Finally,
I felt they were stopping further development, and decided
that @command{mailfromd} should use its own @samp{Milter}
implementation. This new library, @command{libgacopyz} was the main
-new feature of the 3.0 release, that was released in November, 2006.
+new feature of the 3.0 release, which was released in November, 2006.
Another major feature was the @option{--dump-macros} option and
@option{macros} to @command{rc.mailfromd} script, that were intended
to facilitate the configuration on @samp{Sendmail} side.
The development of 3.@i{x} (more properly, 3.1.@i{x}) series
concentrated mainly on bug-fixes, while the main development was done
@@ -518,13 +517,13 @@ lots of new features in @acronym{MFL} syntax and the
library of useful @acronym{MFL} functions. The runtime engine was
also improved, in particular, stack space become expandable which
eliminated many run-time errors. This version also provided a
foundation for @acronym{MFL} module system. The code generation
was re-implemented to facilitate introduction of object files in
future versions. Another new features in this release include
-@acronym{SPF} support and @command{mtasim} utility, an @acronym{MTA}
+@acronym{SPF} support and @command{mtasim} utility --- an @acronym{MTA}
simulator designed for testing @command{mailfromd} scripts
(@pxref{mtasim}). The test suite in this version was made portable by
rewriting it in @i{Autotest}.
Another big leap forward was the 5.0 release, which appeared on
December 26, 2008. It largely enriched a set of available functions
@@ -538,15 +537,15 @@ Mailutils version requirements to at least 2.0.
Version 6.0, which was released in on 12 December, 2009, introduced
a full-fledged modular system, akin to that of Python, and quite a few
improvements to the language. such as explicit type casts,
concatenation operator, static variables, etc.
- Starting from version 7.0, main focus of further development of
-@command{mailfromd} has shifted. While previously it was regarded
-as a mail-filtering server, now it is being developed as a system for
+ Starting from version 7.0, the focus of further development of
+@command{mailfromd} has shifted. While previously it had been regarded
+as a mail-filtering server, since then it was developed as a system for
extending @acronym{MTA} functionality in the broad sense, mail
filtering being only one of features it provides.
Version 7.0 makes the @acronym{MFL} syntax more consistent and the
language itself more powerful. For example, it is no longer necessary
to use prefixes before variables to dereference them. The new
@@ -6465,16 +6464,12 @@ returns true. Otherwise, its result is false.
@end smallexample
@noindent
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{MAX_DNS_MX} @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}.
The value of any parenthesized subexpression occurring within the
right-hand side argument to @code{matches} or @code{mx matches} can be
referenced using the notation @samp{\@var{d}}, where @var{d} is the
@@ -9085,13 +9080,12 @@ program calloutd @{
* conf-debug:: Logging and Debugging configuration
* conf-timeout:: Timeout Configuration
* conf-callout:: Call-out Configuration
* conf-priv:: Privilege Configuration
* conf-database:: Database Configuration
* conf-runtime:: Runtime Constants
-* conf-other:: Other Configuration Statements
* conf-mailutils:: Standard Mailutils Statements
@end menu
@node conf-types
@section Special Configuration Data Types
@@ -9529,17 +9523,12 @@ equivalent to
@smallexample
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{MAX_DNS_MX}.
-@end deffn
-
@deffn {Mailfromd Conf} enable-vrfy bool
@cindex VRFY, SMTP statement
Enables the use of SMTP VRFY statement prior to normal callout
sequence. If VRFY is supported by the remote server,
@command{mailfromd} relies on its reply and does not perform normal
callout.
@@ -9677,40 +9666,12 @@ is used by @acronym{MFL} mailbox functions (@pxref{Mailbox functions}).
@deffn {runtime} max-open-messages number
Sets the maximum number of messages that can be opened simultaneously
using the @code{mailbox_get_message} function. @xref{Message
functions}, for details.
@end deffn
-@deffn {runtime} max-dns-reply-a number
-Sets the maximum number of @acronym{DNS} @samp{A} records to be
-returned in a reply. This affects the @code{dns_getaddr} function
-(@pxref{DNS functions, dns_getaddr}). The default value is @value{MAX_DNS_A}.
-@end deffn
-
-@deffn {runtime} max-dns-reply-ptr number
-Sets the maximum number of @acronym{DNS} @samp{PTR} records to be
-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{MAX_DNS_MX}.
-@end deffn
-
-
@node conf-mailutils
@section Standard Mailutils Statements
The following standard Mailutils statements are understood:
@multitable @columnfractions 0.3 0.6
diff --git a/doc/upgrade.texi b/doc/upgrade.texi
index ab7f7ecb..03c3f595 100644
--- a/doc/upgrade.texi
+++ b/doc/upgrade.texi
@@ -7,12 +7,13 @@
The following sections describe procedures for upgrading
between the consecutive Mailfromd releases.
@menu
+* 820-830:: Upgrading from 8.2 to 8.3
* 700-800:: Upgrading from 7.0 to 8.0
* 600-700:: Upgrading from 6.0 to 7.0
* 5x0-600:: Upgrading from 5.x to 6.0
* 500-510:: Upgrading from 5.0 to 5.1
* 440-500:: Upgrading from 4.4 to 5.0
* 43x-440:: Upgrading from 4.3.x to 4.4
@@ -22,12 +23,34 @@ between the consecutive Mailfromd releases.
* 31x-400:: Upgrading from 3.1.x to 4.0
* 30x-31x:: Upgrading from 3.0.x to 3.1
* 2x-30x:: Upgrading from 2.x to 3.0.x
* 1x-2x:: Upgrading from 1.x to 2.x
@end menu
+@node 820-830
+@appendixsec Upgrading from 8.2 to 8.3
+@cindex Upgrading from 8.2 to 8.3
+
+ Version 8.3 contains significant improvements in the DNS
+resolver. In particular, it removes arbitrary limits on the sizes
+of the RRs. Consequently, the following configurations statements
+are withdrawn:
+
+@table @code
+@item runtime.max-dns-reply-a
+
+@item runtime.max-dns-reply-ptr
+
+@item runtime.max-dns-reply-mx
+
+@item max-match-mx
+
+@item max-callout-mx
+@end table
+
+
@node 700-800
@appendixsec Upgrading from 7.0 to 8.0
@cindex Upgrading from 7.0 to 8.0
Version 8.0 is a major rewrite, that introduces a lot of new
concepts and features. Nevertheless, it is still able to run
diff --git a/lib/dns.c b/lib/dns.c
index e23e9ce7..73c23649 100644
--- a/lib/dns.c
+++ b/lib/dns.c
@@ -28,12 +28,13 @@
#include <netdb.h>
#include <resolv.h>
#include "libmf.h"
#include "dns.h"
#include "mailutils/alloc.h"
+#include "mailutils/argcv.h"
struct mx_buffer {
unsigned pref;
char *name;
};
@@ -67,14 +68,16 @@ comp_pref(const void *a, const void *b)
Let's hope that someday this stupidity will change. */
static dns_status
_getmx(const char *host, unsigned char *answer, size_t answer_size,
struct mxbuf *mxbuf, unsigned long *pttl)
{
- int i, n, nmx;
- struct mx_buffer mx_buffer[MAXMXCOUNT];
+ struct mx_buffer *mx_buffer = NULL;
+ size_t mx_max = 0;
+ size_t nmx = 0;
+ int i, n;
HEADER *hp;
unsigned char *eom, *cp;
unsigned short qdcount, ancount;
struct __res_state stat;
mu_debug(debug_handle, MU_DEBUG_TRACE8,
@@ -146,29 +149,34 @@ _getmx(const char *host, unsigned char *answer, size_t answer_size,
}
GETSHORT(pref, cp);
if ((n = dn_expand((u_char *)answer, eom, cp,
tname, sizeof tname)) < 0)
break;
cp += n;
+ if (nmx == mx_max)
+ mx_buffer = mu_2nrealloc(mx_buffer,
+ &mx_max,
+ sizeof(mx_buffer[0]));
+
mx_buffer[nmx].pref = pref;
- mx_buffer[nmx].name = strdup(tname);
+ mx_buffer[nmx].name = mu_strdup(tname);
mu_debug(debug_handle, MU_DEBUG_TRACE2,
("MX %u %s", mx_buffer[nmx].pref,
mx_buffer[nmx].name));
- if (++nmx >= mxbuf->mx_max)
- break;
+ nmx++;
}
/* Sort according to preference value */
qsort(mx_buffer, nmx, sizeof mx_buffer[0], comp_pref);
/* Prepare return value */
- mxbuf_init(mxbuf);
+ mxbuf_init(mxbuf, nmx);
for (i = 0; i < nmx; i++)
mxbuf->mx_buf[i] = mx_buffer[i].name;
- mxbuf->mx_cnt = nmx;
+ mxbuf->mx_cnt = i;
+ free(mx_buffer);
return dns_success;
}
int
dns_str_is_ipv4(const char *addr)
{
@@ -208,55 +216,54 @@ dns_get_mx_records(const char *host, int maxdepth, struct mxbuf *mxbuf,
status = mf_to_dns_status(resolve_ipstr(host, &hbuf));
if (status != dns_success)
host = NULL;
}
if (host) {
- unsigned char *answer = malloc(MAXPACKET);
- if (!answer)
- status = dns_failure;
- else {
+ unsigned char *answer = mu_alloc(MAXPACKET);
const char *p;
int depth;
for (p = host, depth = 0; p && depth < maxdepth;
p++, depth++) {
if (ttl)
*ttl = ~(unsigned long)0;
- status = _getmx(p, answer, MAXPACKET, mxbuf,
- ttl);
+ status = _getmx(p, answer, MAXPACKET, mxbuf, ttl);
if (status == dns_success
|| status == dns_temp_failure)
break;
p = strchr(p, '.');
if (!p)
break;
}
free(answer);
}
- }
MUTEX_UNLOCK(dns_mutex);
free(hbuf);
return status;
}
void
-mxbuf_init(struct mxbuf *mxbuf)
+mxbuf_init(struct mxbuf *mxbuf, size_t nmx)
{
- if (!(mxbuf->mx_flags & MXF_MAX))
- mxbuf->mx_max = MAXMXCOUNT;
if (mxbuf->mx_flags & MXF_REUSE) {
- int i;
+ size_t i;
- for (i = 0; i < mxbuf->mx_max && mxbuf->mx_buf[i]; i++) {
+ for (i = 0; i < mxbuf->mx_cnt; i++) {
free(mxbuf->mx_buf[i]);
mxbuf->mx_buf[i] = NULL;
}
+ if (nmx > mxbuf->mx_max) {
+ mxbuf->mx_buf =
+ mu_realloc(mxbuf->mx_buf,
+ nmx * sizeof(mxbuf->mx_buf[0]));
+ mxbuf->mx_max = nmx;
+ }
} else {
- mxbuf->mx_buf = mu_calloc(mxbuf->mx_max,
- sizeof(mxbuf->mx_buf[0]));
+ mxbuf->mx_buf = mu_calloc(nmx, sizeof(mxbuf->mx_buf[0]));
+ mxbuf->mx_max = nmx;
mxbuf->mx_flags |= MXF_REUSE;
}
mxbuf->mx_cnt = 0;
}
void
@@ -264,33 +271,72 @@ 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]);
+ free(mxbuf->mx_buf);
mxbuf->mx_buf = NULL;
+ mxbuf->mx_flags &= ~MXF_REUSE;
+ mxbuf->mx_cnt = mxbuf->mx_max = 0;
}
}
#define LOOKUP_FAILURE -1
#define LOOKUP_SUCCESS 0
#define LOOKUP_CNAME 1
+void
+dns_reply_free(struct dns_reply *r)
+{
+ if (r->base) {
+ size_t i;
+ for (i = 0; i < r->count; i++)
+ free(r->base[i]);
+ free(r->base);
+ }
+}
+
+static void
+dns_reply_append(struct dns_reply *r, void *ptr, size_t len, int last)
+{
+ if (r->count == r->max)
+ r->base = mu_2nrealloc(r->base,
+ &r->max,
+ sizeof(r->base[0]));
+ if (last && r->count) {
+ while (r->last_len + len > r->last_max)
+ r->base[r->count-1] =
+ mu_2nrealloc(r->base[r->count-1],
+ &r->last_max,
+ 1);
+ } else if (ptr == NULL) {
+ r->base[r->count] = NULL;
+ return;
+ } else {
+ r->base[r->count] = mu_alloc(len);
+ r->count++;
+ r->last_len = 0;
+ r->last_max = len;
+ }
+
+ memcpy((char*)r->base[r->count-1] + r->last_len, ptr, len);
+ r->last_len += len;
+}
+
struct loop_data {
int qtype; /* Type of the query */
char *name; /* Key to look up */
size_t name_size; /* Length of the key */
char *domain; /* Domain name */
size_t domain_size; /* Length of the domain name */
unsigned char *answer; /* Answer buffer */
size_t answer_size; /* Size of answer buffer */
/* Return data: */
- char *hbuf; /* Return buffer */
- size_t hbsize; /* Size of return buffer */
- size_t hbcount; /* Number of items returned */
+ struct dns_reply repl;
time_t ttl; /* TTL value */
dns_status status; /* Status */
int atype; /* On input: desired answer type or T_ANY
On output: Answer type */
@@ -428,26 +474,17 @@ cname_loop_body(struct loop_data *lp)
blen -= sizeof(align) - ((u_long)bp % sizeof(align));
bp += sizeof(align) - ((u_long)bp % sizeof(align));
if (bp + n >= nbuf + blen) {
mu_debug(debug_handle, MU_DEBUG_TRACE0,
("size (%d) too big", n));
- } else {
- if (n != sizeof(GACOPYZ_UINT32_T)) {
- mu_debug(debug_handle, MU_DEBUG_TRACE0,
- ("unsupported address size: %d",
- n));
- } else if (lp->hbcount * sizeof(GACOPYZ_UINT32_T) >= lp->hbsize)
+ } else if (n != sizeof(GACOPYZ_UINT32_T)) {
mu_debug(debug_handle, MU_DEBUG_TRACE0,
- ("Too many addresses"));
- else {
- memmove((GACOPYZ_UINT32_T *)
- lp->hbuf + lp->hbcount,
- cp, n);
- lp->hbcount++;
- }
+ ("unsupported address size: %d", n));
+ } else {
+ dns_reply_append(&lp->repl, cp, n, 0);
}
bp += n;
blen -= n;
lp->atype = T_A;
SET_STATUS(lp, dns_success);
break;
@@ -458,38 +495,34 @@ cname_loop_body(struct loop_data *lp)
if ((rc = dn_expand((unsigned char *)lp->answer,
eom, cp,
nbuf, sizeof(nbuf))) < 0) {
SET_STATUS(lp, dns_failure);
return LOOKUP_FAILURE;
}
- l = strlen(nbuf);
- if (lp->hbcount + l >= lp->hbsize)
- break;
- memcpy(lp->hbuf + lp->hbcount, nbuf, l);
- lp->hbcount += l;
- lp->hbuf[lp->hbcount++] = 0;
+ dns_reply_append(&lp->repl, nbuf, strlen(nbuf) + 1, 0);
lp->atype = T_PTR;
SET_STATUS(lp, dns_success);
break;
case T_TXT:
if (lp->atype != type)
continue;
else {
unsigned char *cur, *end;
+ int i = 0;
+
cur = cp;
end = cp + n;
while (cur < end) {
l = *cur++;
- if (lp->hbcount + l >= lp->hbsize)
- break;
- memcpy(lp->hbuf + lp->hbcount, cur, l);
- lp->hbcount += l;
- cur += l;
+ dns_reply_append(&lp->repl,
+ cur, l,
+ i > 0);
+ i++;
}
- lp->hbuf[lp->hbcount++] = 0;
+ dns_reply_append(&lp->repl, "", 1, 1);
lp->atype = T_TXT;
SET_STATUS(lp, dns_success);
}
break;
case T_CNAME:
@@ -531,12 +564,20 @@ cname_loop_body(struct loop_data *lp)
}
static void
cnameloop(struct loop_data *lp)
{
MUTEX_LOCK(dns_mutex);
+
+ lp->ttl = ~(unsigned long)0;
+ lp->repl.base = NULL;
+ lp->repl.max = 0;
+ lp->repl.count = 0;
+ lp->status = dns_failure;
+ lp->loopcnt = MAXCNAMEDEPTH;
+
if (!lp->answer) {
static unsigned char *answer;
if (!answer)
answer = mu_alloc(MAXPACKET);
lp->answer = answer;
lp->answer_size = MAXPACKET;
@@ -584,13 +625,13 @@ dns_reverse_ipstr(const char *ipstr, char *revipstr)
return *p || i != 4;
}
dns_status
dns_resolve_ipstr(const char *ipstr, const char *domain,
unsigned char *answer, size_t answer_size,
- char *hbuf, size_t hbsize, unsigned long *ttl)
+ char **hbuf, unsigned long *ttl)
{
char namebuf[NSIZE];
char domainbuf[NSIZE];
struct loop_data ld;
ld.qtype = ld.atype = T_ANY;
@@ -610,37 +651,35 @@ dns_resolve_ipstr(const char *ipstr, const char *domain,
ld.domain = domainbuf;
strcpy(domainbuf, domain ? domain : "in-addr.arpa");
ld.domain_size = sizeof domainbuf;
ld.answer = answer;
ld.answer_size = answer_size;
- ld.hbuf = hbuf;
- ld.hbsize = hbsize;
- ld.hbcount = 0;
- ld.ttl = ~(unsigned long)0;
- ld.status = dns_failure;
- ld.loopcnt = MAXCNAMEDEPTH;
cnameloop(&ld);
- if (ld.status == dns_success && ld.atype == T_A) {
+ if (ld.status == dns_success) {
+ if (ld.atype == T_A) {
struct in_addr s;
- char *p;
- s.s_addr = *(GACOPYZ_UINT32_T*)hbuf;
- p = inet_ntoa(s);
- strncpy(hbuf, p, hbsize);
+ s.s_addr = *(GACOPYZ_UINT32_T*)ld.repl.base[0];
+ *hbuf = mu_strdup(inet_ntoa(s));
+ } else if (ld.atype == T_PTR) {
+ *hbuf = mu_strdup(ld.repl.base[0]);
+ } else
+ abort();
+ dns_reply_free(&ld.repl);
}
*ttl = ld.ttl;
return ld.status;
}
dns_status
dns_resolve_hostname(const char *host,
unsigned char *answer, size_t answer_size,
- char *ipbuf, size_t ipbsize, unsigned long *ttl)
+ char **ipbuf, unsigned long *ttl)
{
struct loop_data ld;
char namebuf[NSIZE];
char domainbuf[NSIZE];
domainbuf[0] = 0;
@@ -650,89 +689,58 @@ dns_resolve_hostname(const char *host,
ld.name = namebuf;
ld.name_size = sizeof namebuf;
ld.domain = domainbuf;
ld.domain_size = sizeof domainbuf;
ld.answer = answer;
ld.answer_size = answer_size;
- ld.hbuf = ipbuf;
- ld.hbsize = ipbsize;
- ld.hbcount = 0;
- ld.ttl = ~(unsigned long)0;
- ld.status = dns_failure;
- ld.loopcnt = MAXCNAMEDEPTH;
cnameloop(&ld);
if (ld.status == dns_success && ld.atype == T_A) {
struct in_addr s;
- char *p;
- s.s_addr = *(GACOPYZ_UINT32_T*)ipbuf;
- p = inet_ntoa(s);
- strncpy(ipbuf, p, ipbsize);
+ s.s_addr = *(GACOPYZ_UINT32_T*)ld.repl.base[0];
+ *ipbuf = mu_strdup(inet_ntoa(s));
+ dns_reply_free(&ld.repl);
}
*ttl = ld.ttl;
return ld.status;
}
dns_status
-a_lookup(const char *host,
- GACOPYZ_UINT32_T *ipbuf, size_t ipbsize, size_t *ipcount,
- unsigned long *ttl, unsigned char *answer, size_t answer_size)
+a_lookup(const char *host, struct dns_reply *repl, unsigned long *ttl)
{
struct loop_data ld;
char namebuf[NSIZE];
char domainbuf[NSIZE];
domainbuf[0] = 0;
ld.qtype = ld.atype = T_A;
strncpy(namebuf, host, sizeof namebuf - 1);
ld.name = namebuf;
ld.name_size = sizeof namebuf;
ld.domain = domainbuf;
ld.domain_size = sizeof domainbuf;
- ld.answer = answer;
- ld.answer_size = answer_size;
- ld.hbuf = (char*) ipbuf;
- ld.hbsize = ipbsize * sizeof ipbuf[0];
- ld.hbcount = 0;
- ld.ttl = ~(unsigned long)0;
- ld.status = dns_failure;
- ld.loopcnt = MAXCNAMEDEPTH;
+ ld.answer = NULL;
+ ld.answer_size = 0;
cnameloop(&ld);
if (ld.status == dns_success) {
- if (ipcount)
- *ipcount = ld.hbcount;
+ *repl = ld.repl;
if (ttl)
*ttl = ld.ttl;
}
return ld.status;
}
-static void
-textbuf_to_argv(const char *hbuf, size_t hsize, char **argv, size_t argc)
-{
- size_t i;
- const char *p;
-
- for (i = 0, p = hbuf; i < argc - 1 && p < hbuf + hsize;
- p += strlen(p) + 1)
- argv[i++] = mu_strdup(p);
- argv[i] = NULL;
-}
-
dns_status
-ptr_lookup(struct in_addr ip,
- char **names, size_t maxnames, unsigned long *ttl,
- unsigned char *answer, size_t answer_size)
+ptr_lookup(struct in_addr ip, struct dns_reply *repl, unsigned long *ttl)
{
char namebuf[NSIZE];
char domainbuf[NSIZE];
- char hbuf[NSIZE];
struct loop_data ld;
char *p;
ip.s_addr = ntohl(ip.s_addr);
p = inet_ntoa(ip);
strncpy(namebuf, p, sizeof namebuf);
@@ -740,142 +748,128 @@ ptr_lookup(struct in_addr ip,
ld.qtype = ld.atype = T_PTR;
ld.name = namebuf;
ld.name_size = sizeof namebuf;
ld.domain = domainbuf;
strcpy(domainbuf, "in-addr.arpa");
ld.domain_size = sizeof domainbuf;
- ld.answer = answer;
- ld.answer_size = answer_size;
- ld.hbuf = hbuf;
- ld.hbsize = sizeof hbuf;
- ld.hbcount = 0;
- ld.ttl = ~(unsigned long)0;
- ld.status = dns_failure;
- ld.loopcnt = MAXCNAMEDEPTH;
+ ld.answer = NULL;
+ ld.answer_size = 0;
cnameloop(&ld);
if (ld.status == dns_success) {
- textbuf_to_argv(ld.hbuf, ld.hbcount, names, maxnames);
+ *repl = ld.repl;
if (ttl)
*ttl = ld.ttl;
}
return ld.status;
}
dns_status
-txt_lookup(const char *name,
- char **names, size_t maxnames, unsigned long *ttl,
- unsigned char *answer, size_t answer_size)
+txt_lookup(const char *name, struct dns_reply *repl, unsigned long *ttl)
{
char domainbuf[NSIZE];
- char hbuf[NSIZE];