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,2 +1,2 @@ -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 @@ -7,2 +7,19 @@ 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 diff --git a/configure.ac b/configure.ac index 53e87421..2dd23baa 100644 --- a/configure.ac +++ b/configure.ac @@ -19,3 +19,3 @@ 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], diff --git a/doc/calloutd.texi b/doc/calloutd.texi index 87f5d621..5bd91916 100644 --- a/doc/calloutd.texi +++ b/doc/calloutd.texi @@ -83,3 +83,2 @@ 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}. diff --git a/doc/functions.texi b/doc/functions.texi index b5a33c7e..a9fb3e36 100644 --- a/doc/functions.texi +++ b/doc/functions.texi @@ -1922,5 +1922,3 @@ require dns 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}. @@ -1931,5 +1929,3 @@ to change this limit. 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}. @@ -1957,8 +1953,4 @@ getmx("org.pl") @result{} "" -@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}. @@ -2058,6 +2050,2 @@ exception @code{e_not_found}. @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 @@ -2075,6 +2063,2 @@ records for the @var{domain}. Otherwise it 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 diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi index 05c9e839..d28915f9 100644 --- a/doc/mailfromd.texi +++ b/doc/mailfromd.texi @@ -341,3 +341,2 @@ Configuring @command{mailfromd} * conf-runtime:: Runtime Constants -* conf-other:: Other Configuration Statements * conf-mailutils:: Standard Mailutils Statements @@ -473,3 +472,3 @@ possibilities. 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, @@ -477,23 +476,23 @@ 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. @@ -504,3 +503,3 @@ 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 @@ -523,3 +522,3 @@ 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 @@ -543,5 +542,5 @@ 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 @@ -6470,6 +6469,2 @@ 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 @@ -9090,3 +9085,2 @@ program calloutd @{ * conf-runtime:: Runtime Constants -* conf-other:: Other Configuration Statements * conf-mailutils:: Standard Mailutils Statements @@ -9534,7 +9528,2 @@ setvar mailfrom_address @var{string}; -@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 @@ -9682,30 +9671,2 @@ functions}, for details. -@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 diff --git a/doc/upgrade.texi b/doc/upgrade.texi index ab7f7ecb..03c3f595 100644 --- a/doc/upgrade.texi +++ b/doc/upgrade.texi @@ -12,2 +12,3 @@ between the consecutive Mailfromd releases. @menu +* 820-830:: Upgrading from 8.2 to 8.3 * 700-800:: Upgrading from 7.0 to 8.0 @@ -27,2 +28,24 @@ between the consecutive Mailfromd releases. +@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 @@ -33,2 +33,3 @@ #include "mailutils/alloc.h" +#include "mailutils/argcv.h" @@ -72,4 +73,6 @@ _getmx(const char *host, unsigned char *answer, size_t answer_size, { - 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; @@ -151,4 +154,9 @@ _getmx(const char *host, unsigned char *answer, size_t answer_size, 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, @@ -156,4 +164,3 @@ _getmx(const char *host, unsigned char *answer, size_t answer_size, mx_buffer[nmx].name)); - if (++nmx >= mxbuf->mx_max) - break; + nmx++; } @@ -164,6 +171,7 @@ _getmx(const char *host, unsigned char *answer, size_t answer_size, /* 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; @@ -213,6 +221,3 @@ dns_get_mx_records(const char *host, int maxdepth, struct mxbuf *mxbuf, if (host) { - unsigned char *answer = malloc(MAXPACKET); - if (!answer) - status = dns_failure; - else { + unsigned char *answer = mu_alloc(MAXPACKET); const char *p; @@ -224,4 +229,3 @@ dns_get_mx_records(const char *host, int maxdepth, struct mxbuf *mxbuf, *ttl = ~(unsigned long)0; - status = _getmx(p, answer, MAXPACKET, mxbuf, - ttl); + status = _getmx(p, answer, MAXPACKET, mxbuf, ttl); if (status == dns_success @@ -235,3 +239,2 @@ dns_get_mx_records(const char *host, int maxdepth, struct mxbuf *mxbuf, } - } MUTEX_UNLOCK(dns_mutex); @@ -242,10 +245,8 @@ dns_get_mx_records(const char *host, int maxdepth, struct mxbuf *mxbuf, 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]); @@ -253,5 +254,11 @@ mxbuf_init(struct mxbuf *mxbuf) } + 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; @@ -269,3 +276,6 @@ mxbuf_free(struct mxbuf *mxbuf) 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; } @@ -277,2 +287,40 @@ mxbuf_free(struct mxbuf *mxbuf) +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 { @@ -287,5 +335,3 @@ struct loop_data { /* Return data: */ - char *hbuf; /* Return buffer */ - size_t hbsize; /* Size of return buffer */ - size_t hbcount; /* Number of items returned */ + struct dns_reply repl; @@ -433,16 +479,7 @@ cname_loop_body(struct loop_data *lp) ("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); } @@ -463,8 +500,3 @@ cname_loop_body(struct loop_data *lp) } - 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; @@ -478,2 +510,4 @@ cname_loop_body(struct loop_data *lp) unsigned char *cur, *end; + int i = 0; + cur = cp; @@ -482,9 +516,8 @@ cname_loop_body(struct loop_data *lp) 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; @@ -536,2 +569,10 @@ 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) { @@ -589,3 +630,3 @@ 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) { @@ -615,8 +656,2 @@ dns_resolve_ipstr(const char *ipstr, const char *domain, 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; @@ -624,8 +659,12 @@ dns_resolve_ipstr(const char *ipstr, const char *domain, - 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); } @@ -639,3 +678,3 @@ 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) { @@ -655,8 +694,2 @@ dns_resolve_hostname(const char *host, 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; @@ -666,6 +699,5 @@ dns_resolve_hostname(const char *host, 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); } @@ -678,5 +710,3 @@ dns_resolve_hostname(const char *host, 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) { @@ -693,10 +723,4 @@ a_lookup(const char *host, 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; @@ -704,4 +728,3 @@ a_lookup(const char *host, if (ld.status == dns_success) { - if (ipcount) - *ipcount = ld.hbcount; + *repl = ld.repl; if (ttl) @@ -712,18 +735,4 @@ a_lookup(const char *host, -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) { @@ -731,3 +740,2 @@ ptr_lookup(struct in_addr ip, char domainbuf[NSIZE]; - char hbuf[NSIZE]; struct loop_data ld; @@ -745,10 +753,4 @@ ptr_lookup(struct in_addr ip, 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; @@ -757,3 +759,3 @@ ptr_lookup(struct in_addr ip, if (ld.status == dns_success) { - textbuf_to_argv(ld.hbuf, ld.hbcount, names, maxnames); + *repl = ld.repl; if (ttl) @@ -766,8 +768,5 @@ ptr_lookup(struct in_addr ip, 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]; struct loop_data ld; @@ -781,10 +780,4 @@ txt_lookup(const char *name, 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; @@ -795,3 +788,3 @@ txt_lookup(const char *name, if (ld.status == dns_success) { - textbuf_to_argv(ld.hbuf, ld.hbcount, names, maxnames); + *repl = ld.repl; if (ttl) @@ -803,12 +796,15 @@ txt_lookup(const char *name, -/* FIXME: This is a placeholder for a function that should look up for any - SPF or TXT records for DOMAIN. If any SPF are found, TXT should be - discarded. - For the time being, it handles only TXT */ dns_status spf_lookup(const char *domain, - char **txt, size_t maxtxt, unsigned long *ttl, - unsigned char *answer, size_t answer_size) + char ***txtv, size_t *txtc, unsigned long *ttl) { - return txt_lookup(domain, txt, maxtxt, ttl, answer, answer_size); + dns_status res; + struct dns_reply r; + res = txt_lookup(domain, &r, ttl); + if (res == dns_success) { + *txtv = (char**)r.base; + if (txtc) + *txtc = r.count; + } + return res; } @@ -821,5 +817,3 @@ ptr_validate(const char *ipstr, char ***vnptr, size_t *vcount, struct in_addr ip; - char *names[11], **p; - char *vnames[10]; - size_t vi = 0; + size_t i; int status; @@ -827,2 +821,6 @@ ptr_validate(const char *ipstr, char ***vnptr, size_t *vcount, unsigned long ttl; + struct dns_reply ptr_repl; + char **sv = NULL; + size_t sc = 0; + size_t sn = 0; @@ -831,3 +829,3 @@ ptr_validate(const char *ipstr, char ***vnptr, size_t *vcount, - status = ptr_lookup(ip, names, NELEMS(names), &ttl, NULL, 0); + status = ptr_lookup(ip, &ptr_repl, &ttl); @@ -837,19 +835,15 @@ ptr_validate(const char *ipstr, char ***vnptr, size_t *vcount, UPDATE_TTL(minttl, ttl); - - for (p = names; *p; p++) { - GACOPYZ_UINT32_T ipbuf[10]; - size_t ipcount; - status = a_lookup(*p, - ipbuf, NELEMS(ipbuf), - &ipcount, - &ttl, NULL, 0); - if (status == dns_success && vi < NELEMS(vnames[0])) { - size_t i; + for (i = 0; i < ptr_repl.count; i++) { + struct dns_reply r; + status = a_lookup((char*)ptr_repl.base[i], &r, &ttl); + if (status == dns_success) { + size_t k; UPDATE_TTL(minttl, ttl); - for (i = 0; i < ipcount; i++) - if (ipbuf[i] == ip.s_addr) { - vnames[vi++] = *p; - if (vnptr) - *p = NULL; + for (k = 0; k < r.count; k++) { + if (dns_reply_ip(&r, k) == ip.s_addr) { + if (sc == sn) + sv = mu_2nrealloc(sv, &sn, + sizeof(sv[0])); + sv[sc++] = mu_strdup(ptr_repl.base[i]); break; @@ -857,20 +851,20 @@ ptr_validate(const char *ipstr, char ***vnptr, size_t *vcount, } - free(*p); + dns_reply_free(&r); + } } + dns_reply_free(&ptr_repl); - if (vi > 0) { + if (sc == 0) { + return dns_not_found; + } if (pttl) *pttl = minttl; - if (vnptr) { - size_t i; - - *vnptr = mu_calloc(vi+1, sizeof vnptr[0]); - for (i = 0; i < vi; i++) - (*vnptr)[i] = vnames[i]; - (*vnptr)[i] = NULL; - *vcount = vi; - } - } + if (vcount) + *vcount = sc; + if (vnptr) + *vnptr = sv; + else + mu_argcv_free(sc, sv); - return vi > 0 ? dns_success : dns_not_found; + return dns_success; } @@ -893,3 +887,2 @@ getmx(const char *host, struct mxbuf *mxbuf) { - mxbuf_init(mxbuf); return dns_to_mf_status(dns_get_mx_records(host, 1, mxbuf, NULL)); @@ -898,3 +891,3 @@ getmx(const char *host, struct mxbuf *mxbuf) mf_status -getmxip(char *host, GACOPYZ_UINT32_T *ipbuf, size_t mxmax, size_t *pcount) +getmxip(char *host, GACOPYZ_UINT32_T **pipbuf, size_t *pcount) { @@ -902,7 +895,7 @@ getmxip(char *host, GACOPYZ_UINT32_T *ipbuf, size_t mxmax, size_t *pcount) mf_status mxstat; - size_t ipcount; + GACOPYZ_UINT32_T *ipbuf = NULL; + size_t ipcount = 0; + size_t ipmax = 0; size_t i; - mxbuf.mx_max = mxmax; - mxbuf.mx_flags = MXF_MAX; mxstat = getmx(host, &mxbuf); @@ -913,15 +906,13 @@ getmxip(char *host, GACOPYZ_UINT32_T *ipbuf, size_t mxmax, size_t *pcount) for (i = 0; i < mxbuf.mx_cnt; i++) { - size_t ipn; - dns_status stat = a_lookup(mxbuf.mx_buf[i], - ipbuf + ipcount, - mxmax - ipcount, - &ipn, - NULL, NULL, 0); + struct dns_reply r; + dns_status stat = a_lookup(mxbuf.mx_buf[i], &r, NULL); if (stat == dns_success) { size_t n; - for (n = 0; ipcount < mxmax && n < ipn; - n++, ipcount++) - ipbuf[ipcount] = ntohl(ipbuf[ipcount]); - if (ipcount == mxmax) - break; + for (n = 0; n < r.count; n++, ipcount++) { + if (ipcount == ipmax) + ipbuf = mu_2nrealloc(ipbuf, &ipmax, + sizeof(ipbuf)); + ipbuf[ipcount] = ntohl(dns_reply_ip(&r, n)); + } + dns_reply_free(&r); } @@ -930,2 +921,3 @@ getmxip(char *host, GACOPYZ_UINT32_T *ipbuf, size_t mxmax, size_t *pcount) mxbuf_free(&mxbuf); + *pipbuf = ipbuf; *pcount = ipcount; @@ -939,3 +931,3 @@ resolve_ipstr_domain(const char *ipstr, const char *domain, char **phbuf) unsigned long ttl; - char buffer[256]; + char *hbuf; dns_status dstat; @@ -948,3 +940,3 @@ resolve_ipstr_domain(const char *ipstr, const char *domain, char **phbuf) dstat = dns_resolve_ipstr(ipstr, domain, answer, MAXPACKET, - buffer, sizeof buffer, &ttl); + &hbuf, &ttl); @@ -953,4 +945,4 @@ resolve_ipstr_domain(const char *ipstr, const char *domain, char **phbuf) mu_debug(debug_handle, MU_DEBUG_TRACE8, - ("%s resolved to %s", ipstr, buffer)); - *phbuf = mu_strdup(buffer); + ("%s resolved to %s", ipstr, hbuf)); + *phbuf = hbuf; break; @@ -974,3 +966,2 @@ resolve_hostname(const char *host, char **pipbuf) static unsigned char *answer; - char buffer[256]; char *ipbuf; @@ -981,3 +972,3 @@ resolve_hostname(const char *host, char **pipbuf) if (!answer) - answer = malloc(MAXPACKET); + answer = mu_alloc(MAXPACKET); mu_debug(debug_handle, MU_DEBUG_TRACE8, @@ -986,4 +977,3 @@ resolve_hostname(const char *host, char **pipbuf) dstat = dns_resolve_hostname(tmphost, answer, MAXPACKET, - buffer, sizeof buffer, - &ttl); + &ipbuf, &ttl); free(tmphost); @@ -991,3 +981,2 @@ resolve_hostname(const char *host, char **pipbuf) case dns_success: - ipbuf = mu_strdup(buffer); mu_debug(debug_handle, MU_DEBUG_TRACE8, @@ -33,5 +33,2 @@ typedef enum { -#define MAXMXCOUNT 32 - -#define MXF_MAX 0x01 #define MXF_REUSE 0x02 @@ -80,3 +77,3 @@ struct mxbuf { -void mxbuf_init(struct mxbuf *mxbuf); +void mxbuf_init(struct mxbuf *mxbuf, size_t n); void mxbuf_free(struct mxbuf *mxbuf); @@ -91,3 +88,3 @@ 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); @@ -95,15 +92,28 @@ 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 dns_reply { + size_t count; + size_t max; + + void **base; + size_t last_len; + size_t last_max; +}; + +void dns_reply_free(struct dns_reply *r); + +static inline GACOPYZ_UINT32_T +dns_reply_ip(struct dns_reply const *repl, size_t n) +{ + return *(GACOPYZ_UINT32_T*)repl->base[n]; +} + 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); + struct dns_reply *repl, unsigned long *ttl); dns_status ptr_lookup(struct in_addr ip, - char **names, size_t maxnames, unsigned long *ttl, - unsigned char *answer, size_t answer_size); + struct dns_reply *repl, unsigned long *ttl); dns_status txt_lookup(const char *name, - char **names, size_t maxnames, unsigned long *ttl, - unsigned char *answer, size_t answer_size); + struct dns_reply *repl, unsigned long *ttl); @@ -112,2 +122,6 @@ dns_status ptr_validate(const char *ipstr, char ***vnptr, size_t *vcount, +dns_status spf_lookup(const char *domain, + char ***txtv, size_t *txtc, unsigned long *ttl); + + #endif diff --git a/lib/libmf.h b/lib/libmf.h index 9842b75c..5336b218 100644 --- a/lib/libmf.h +++ b/lib/libmf.h @@ -285,3 +285,3 @@ dns_status mf_to_dns_status(mf_status stat); mf_status getmx(const char *host, struct mxbuf *mxbuf); -mf_status getmxip(char *host, GACOPYZ_UINT32_T *ipbuf, size_t mxmax, size_t *pcount); +mf_status getmxip(char *host, GACOPYZ_UINT32_T **ipbuf, size_t *pcount); mf_status resolve_ipstr_domain(const char *ipstr, const char *domain, char **phbuf); diff --git a/src/builtin/dns.bi b/src/builtin/dns.bi index 46433a00..faf8998d 100644 --- a/src/builtin/dns.bi +++ b/src/builtin/dns.bi @@ -23,16 +23,2 @@ -static size_t max_ptr = MAX_DNS_PTR; -static size_t max_a = MAX_DNS_A; -static size_t max_mx = MAX_DNS_MX; -static struct mu_cfg_param dns_cfg_param[] = { - { "max-dns-reply-a", mu_c_size, &max_a, 0, NULL, - N_("Maximum number of A records in a DNS reply.") }, - { "max-dns-reply-ptr", mu_c_size, &max_a, 0, NULL, - N_("Maximum number of PTR records in a DNS reply.") }, - { "max-dns-reply-mx", mu_c_size, &max_mx, 0, NULL, - N_("Maximum number of MX records in a DNS reply.") }, - { NULL } -}; - - MF_DEFUN(primitive_hostname, STRING, STRING string) @@ -77,4 +63,4 @@ ipaddr_cmp(const void *a, const void *b) { - GACOPYZ_UINT32_T ipa = ntohl(*(GACOPYZ_UINT32_T*)a); - GACOPYZ_UINT32_T ipb = ntohl(*(GACOPYZ_UINT32_T*)b); + GACOPYZ_UINT32_T ipa = ntohl(**(GACOPYZ_UINT32_T**)a); + GACOPYZ_UINT32_T ipb = ntohl(**(GACOPYZ_UINT32_T**)b); if (ipa < ipb) @@ -88,10 +74,8 @@ MF_DEFUN(dns_getaddr, STRING, STRING string) { - GACOPYZ_UINT32_T *ipbuf; - size_t i, ipcount; + size_t i; unsigned long ttl; dns_status dnstat; + struct dns_reply r; - ipbuf = mu_calloc(max_a, sizeof(ipbuf[0])); - dnstat = a_lookup(string, ipbuf, max_a, &ipcount, - &ttl, NULL, 0); + dnstat = a_lookup(string, &r, &ttl); switch (dnstat) { @@ -99,4 +83,4 @@ MF_DEFUN(dns_geta |