diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | NEWS | 13 | ||||
-rw-r--r-- | doc/mailfromd.texi | 37 | ||||
-rw-r--r-- | src/bi_dns.m4 | 39 | ||||
-rw-r--r-- | src/dns.c | 58 | ||||
-rw-r--r-- | src/mailfromd.h | 1 |
6 files changed, 159 insertions, 2 deletions
@@ -1,3 +1,16 @@ +2007-03-21 Sergey Poznyakoff <gray@gnu.org.ua> + + * src/mailfromd.h (getmxip): New function + * src/dns.c (getmxip): New function + * src/bi_dns.m4: (getmx): New built-in + * doc/mailfromd.texi: Document getmx + + * src/prog.c (mx_match): Do not raise exception if mf_not_found is + returned. + * src/bi_sa.m4 (open_connection): Raise mf_url if unknown protocol + is specified in the URL. + * src/mtasim.c: Minor fix + 2007-03-19 Sergey Poznyakoff <gray@gnu.org.ua> * src/engine.c, src/gram.y, src/status.mfi, doc/mailfromd.texi: @@ -1,4 +1,4 @@ -Mailfromd NEWS -- history of user-visible changes. 2007-03-19 +Mailfromd NEWS -- history of user-visible changes. 2007-03-21 Copyright (C) 2005, 2006, 2007 Sergey Poznyakoff See the end of file for copying conditions. @@ -27,6 +27,17 @@ Return full file name of the database file corresponding to format Return the expiration period for db format `fmt' +- string getmx(string domain [, number resolve]) + +Returns a whitespace-separated list of MX names (if `resolve' is not +given or is 0) or MX IP addresses (if `resolve'==1) for `domain'. If +`domain' has no MX records, empty string is returned. If the DNS +query fails, `getmx' raises an appropriate exception. + +This interface differs from that of version 3.1.4 in that the calls to +getmx(domain) and getmx(domain,1) can return different number of +entries (see the docs for an example). + * #pragma regex stack The `#pragma regex' statement can keep a stack of regex flags. The diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi index 63e677e8..8dd33e3b 100644 --- a/doc/mailfromd.texi +++ b/doc/mailfromd.texi @@ -4520,7 +4520,6 @@ fi @end smallexample @end deftypefn - @node DNS functions @subsubsection DNS Functions @@ -4539,6 +4538,42 @@ without throwing exceptions. The built-in layer is always available. The library calls become available after inclusion of @file{dns.mf}. +@deftypefn {Built-in Function} string getmx (string @var{domain} @ + [, number @var{resolve}]) + Returns a whitespace-separated list of MX names (if @var{resolve} is not +given or if it is @code{0}) or MX IP addresses (if +@code{@var{resolve}!=0})) for @var{domain}. Within the returned +strings, items are sorted lexicographically. If @var{domain} has no +MX records, empty string is returned. If the DNS query fails, +@code{getmx} raises an appropriate exception. + +@emph{Notes}: +@enumerate 1 +@item The @code{getmx} function returns at most 32 MX names or IP addresses. + +@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 +getmx("aol.com") + @result{} mailin-01.mx.aol.com mailin-02.mx.aol.com + mailin-03.mx.aol.com mailin-04.mx.aol.com +getmx("aol.com", 1) + @result{} 64.12.137.89 64.12.137.168 64.12.137.184 + 64.12.137.249 64.12.138.57 64.12.138.88 + 64.12.138.120 64.12.138.185 205.188.155.89 + 205.188.156.185 205.188.156.249 205.188.157.25 + 205.188.157.217 205.188.158.121 205.188.159.57 + 205.188.159.217 +@end group +@end smallexample + +@item This interface will change in future releases, when array +data types are implemented. +@end enumerate +@end deftypefn + @anchor{primitive_hasmx} @deftypefn {Built-in Function} boolean primitive_hasmx (string @var{domain}) Returns @code{true} if the domain name given by its argument diff --git a/src/bi_dns.m4 b/src/bi_dns.m4 index aa179492..021f2d08 100644 --- a/src/bi_dns.m4 +++ b/src/bi_dns.m4 @@ -78,6 +78,45 @@ MF_DEFUN(primitive_hasmx, NUMBER, STRING string) } END +MF_DEFUN(getmx, STRING, STRING domain, OPTIONAL, NUMBER resolve) +{ + mxbuf_t mxbuf; + mf_status mxstat; + int i; + + if (resolve) + mxstat = getmxip(domain, mxbuf); + else + mxstat = getmx(domain, mxbuf); + MF_ASSERT(mxstat == mf_success || mxstat == mf_not_found, + mxstat, + "Cannot get MX records for %s", domain); + if (mxstat == mf_not_found) + MF_RETURN_STRING(""); + else { + int i; + size_t ns; + char *p; + + MF_BEGIN_TEMP_SPACE(s, size); + + for (i = 0, ns = 0, p = s; mxbuf[i]; i++) { + size_t len = strlen(mxbuf[i]); + if (ns + len + 1 > size) + break; + if (i > 0) + *p++ = ' '; + memcpy(p, mxbuf[i], len); + p += len; + ns += len + 1; + } + *p = 0; + dns_freemx(mxbuf); + MF_RETURN_TEMP_SPACE(ns); + } +} +END + static int resolve_host(const char *string, unsigned long *ip) { @@ -55,6 +55,64 @@ getmx(char *host, mxbuf_t mxbuf) return rc; } +static int +comp_ipbuf(const void *a, const void *b) +{ + const GACOPYZ_UINT32_T *in_a = a; + const GACOPYZ_UINT32_T *in_b = b; + + if (*in_a < *in_b) + return -1; + else if (*in_a > *in_b) + return 1; + return 0; +} + +mf_status +getmxip(char *host, mxbuf_t mxbuf) +{ + mf_status mxstat; + GACOPYZ_UINT32_T ipbuf[MAXMXCOUNT]; + size_t ipcount; + size_t i; + + mxstat = getmx(host, mxbuf); + if (mxstat != mf_success) + return mxstat; + + ipcount = 0; + for (i = 0; i < MAXMXCOUNT && mxbuf[i]; i++) { + size_t ipn; + mf_status stat = a_lookup(mxbuf[i], + ipbuf + ipcount, + NELEMS(ipbuf) - ipcount, + &ipn, + NULL, NULL, 0); + if (stat == mf_success) { + size_t n; + for (n = 0; ipcount < NELEMS(ipbuf) && n < ipn; + n++, ipcount++) + ipbuf[ipcount] = ntohl(ipbuf[ipcount]); + if (ipcount == NELEMS(ipbuf)) + break; + } + } + + dns_freemx(mxbuf); + + qsort(ipbuf, ipcount, sizeof ipbuf[0], comp_ipbuf); + + for (i = 0; i < ipcount; i++) { + struct in_addr s; + s.s_addr = htonl(ipbuf[i]); + mxbuf[i] = xstrdup(inet_ntoa(s)); + } + + if (i < MAXMXCOUNT) + mxbuf[i] = NULL; + return mf_success; +} + mf_status resolve_ipstr_domain(const char *ipstr, const char *domain, char **phbuf) { diff --git a/src/mailfromd.h b/src/mailfromd.h index 836b4fd0..cb60441a 100644 --- a/src/mailfromd.h +++ b/src/mailfromd.h @@ -132,6 +132,7 @@ mf_status resolve_ipstr_domain(const char *ipstr, const char *domain, mf_status resolve_hostname(const char *host, char **pipbuf); mf_status getmx(char *ipstr, mxbuf_t mxbuf); +mf_status getmxip(char *ipstr, mxbuf_t mxbuf); /* Default file names */ |