diff options
-rw-r--r-- | NEWS | 19 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | doc/calloutd.texi | 1 | ||||
-rw-r--r-- | doc/functions.texi | 22 | ||||
-rw-r--r-- | doc/mailfromd.texi | 89 | ||||
-rw-r--r-- | doc/upgrade.texi | 23 | ||||
-rw-r--r-- | lib/dns.c | 363 | ||||
-rw-r--r-- | lib/dns.h | 42 | ||||
-rw-r--r-- | lib/libmf.h | 2 | ||||
-rw-r--r-- | src/builtin/dns.bi | 90 | ||||
-rw-r--r-- | src/callout.c | 2 | ||||
-rw-r--r-- | src/mailfromd.h | 3 | ||||
-rw-r--r-- | src/main.c | 5 | ||||
-rw-r--r-- | src/prog.c | 2 | ||||
-rw-r--r-- | src/spf.c | 78 | ||||
-rw-r--r-- | src/spf.h | 3 | ||||
-rw-r--r-- | src/srvcfg.c | 5 |
17 files changed, 348 insertions, 403 deletions
@@ -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 @@ -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]; |