aboutsummaryrefslogtreecommitdiff
path: root/mfd/bi_dns.m4
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2008-02-10 14:08:36 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2008-02-10 14:08:36 +0000
commita1871918823166cac9f0c12164ba27cb3b1f0c2c (patch)
tree7260d118aa5af6a8f006f9b2dac6cabde782db8c /mfd/bi_dns.m4
parent455b645247bdc0f01239b2352a9d8f07f446024f (diff)
downloadmailfromd-a1871918823166cac9f0c12164ba27cb3b1f0c2c.tar.gz
mailfromd-a1871918823166cac9f0c12164ba27cb3b1f0c2c.tar.bz2
Merged HEAD from branches/gmach
git-svn-id: file:///svnroot/mailfromd/trunk@1612 7a8a7f39-df28-0410-adc6-e0d955640f24
Diffstat (limited to 'mfd/bi_dns.m4')
-rw-r--r--mfd/bi_dns.m4297
1 files changed, 297 insertions, 0 deletions
diff --git a/mfd/bi_dns.m4 b/mfd/bi_dns.m4
new file mode 100644
index 00000000..6ca93d17
--- /dev/null
+++ b/mfd/bi_dns.m4
@@ -0,0 +1,297 @@
+/* This file is part of Mailfromd. -*- c -*-
+ Copyright (C) 2006, 2007, 2008 Sergey Poznyakoff
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+MF_DEFUN(primitive_hostname, STRING, STRING string)
+{
+ char *hbuf;
+ mf_status stat;
+
+ stat = resolve_ipstr(string, &hbuf);
+ MF_ASSERT(stat == mf_success,
+ stat,
+ _("Cannot resolve IP %s"),
+ string);
+
+ pushs(env, hbuf);
+ free(hbuf);
+}
+END
+
+MF_DEFUN(primitive_resolve, STRING, STRING string, OPTIONAL, STRING domain)
+{
+ char *ipstr;
+ mf_status stat;
+
+ if (MF_OPTVAL(domain,"")[0]) {
+ stat = resolve_ipstr_domain(string, domain, &ipstr);
+ MF_ASSERT(stat == mf_success,
+ stat,
+ _("Cannot resolve %s.%s"), string, domain);
+ } else {
+ stat = resolve_hostname(string, &ipstr);
+ MF_ASSERT(stat == mf_success,
+ stat,
+ _("Cannot resolve %s"), string);
+ }
+ pushs(env, ipstr);
+ free(ipstr);
+}
+END
+
+static int
+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);
+ if (ipa < ipb)
+ return -1;
+ if (ipa > ipb)
+ return 1;
+ return 0;
+}
+
+MF_DEFUN(dns_getaddr, STRING, STRING string)
+{
+ GACOPYZ_UINT32_T ipbuf[64]; /* FIXME: arbitrary limit */
+ size_t i, ipcount;
+ unsigned long ttl;
+ dns_status dnstat;
+
+ dnstat = a_lookup(string, ipbuf, NELEMS(ipbuf), &ipcount,
+ &ttl, NULL, 0);
+ switch (dnstat) {
+ case dns_success: {
+ MF_OBSTACK_BEGIN();
+ qsort(ipbuf, ipcount, sizeof ipbuf[0], ipaddr_cmp);
+ for (i = 0; i < ipcount; i++) {
+ struct in_addr addr;
+ char *q;
+
+ addr.s_addr = ipbuf[i];
+ q = inet_ntoa(addr);
+ if (i > 0)
+ MF_OBSTACK_1GROW(' ');
+ MF_OBSTACK_GROW(q);
+ }
+ MF_OBSTACK_1GROW(0);
+ MF_RETURN_OBSTACK();
+ }
+ case dns_not_found:
+ MF_RETURN_STRING("");
+ default:
+ MF_THROW(dns_to_mf_status(dnstat),
+ _("Failed to get A record for %s"), string);
+ }
+}
+END
+
+static int
+hostname_cmp(const void *a, const void *b)
+{
+ return strcmp(*(const char**) a, *(const char**) b);
+}
+
+MF_DEFUN(dns_getname, STRING, STRING ipstr)
+{
+ dns_status dnstat;
+ struct in_addr addr;
+ unsigned long ttl;
+ char *names[64];
+
+ MF_ASSERT(inet_aton(ipstr, &addr),
+ mf_invip,
+ _("Invalid IP: %s"), ipstr);
+
+ dnstat = ptr_lookup(addr, names, NELEMS(names), &ttl, NULL, 0);
+ switch (dnstat) {
+ case dns_success: {
+ size_t i;
+ size_t ncount;
+
+ for (ncount = 0; ncount < NELEMS(names) && names[ncount];
+ ncount++);
+
+ qsort(names, ncount, sizeof names[0], hostname_cmp);
+
+ for (i = 0; i < ncount; i++) {
+ if (i > 0)
+ MF_OBSTACK_1GROW(' ');
+ MF_OBSTACK_GROW(names[i]);
+ }
+ MF_OBSTACK_1GROW(0);
+
+ for (; i < ncount; i++)
+ free(names[i]);
+
+ MF_RETURN_OBSTACK();
+ }
+ case dns_not_found:
+ MF_RETURN_STRING("");
+ default:
+ MF_THROW(dns_to_mf_status(dnstat),
+ _("Failed to get PTR record for %s"), ipstr);
+ }
+}
+END
+
+MF_DEFUN(primitive_hasmx, NUMBER, STRING string)
+{
+ mxbuf_t mxbuf;
+ mf_status mxstat;
+
+ mxstat = getmx(string, mxbuf);
+
+ MF_ASSERT(mxstat == mf_success || mxstat == mf_not_found,
+ mxstat,
+ _("Cannot get MX records for %s"),
+ string);
+
+ if (mxstat == mf_success) {
+ dns_freemx(mxbuf);
+ MF_RETURN(1);
+ }
+ MF_RETURN(0);
+}
+END
+
+MF_DEFUN(getmx, STRING, STRING domain, OPTIONAL, NUMBER resolve)
+{
+ mxbuf_t mxbuf;
+ mf_status mxstat;
+
+ if (MF_OPTVAL(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;
+
+ MF_OBSTACK_BEGIN();
+ for (i = 0; i < MAXMXCOUNT && mxbuf[i]; i++) {
+ if (i > 0)
+ MF_OBSTACK_1GROW(' ');
+ MF_OBSTACK_GROW(mxbuf[i]);
+ }
+ MF_OBSTACK_1GROW(0);
+ dns_freemx(mxbuf);
+ MF_RETURN_OBSTACK();
+ }
+}
+END
+
+static int
+resolve_host(const char *string, unsigned long *ip)
+{
+ int rc;
+ struct in_addr addr;
+ char *ipstr;
+
+ if (inet_aton(string, &addr)) {
+ *ip = addr.s_addr;
+ return 0;
+ }
+
+ if (resolve_hostname(string, &ipstr) != mf_success)
+ return 1;
+
+ rc = inet_aton(ipstr, &addr);
+ free(ipstr);
+ if (rc == 0) {
+ mu_error(_("INTERNAL ERROR at %s:%d: resolve_hostname returned "
+ "invalid IP address: %s"),
+ __FILE__, __LINE__, ipstr);
+ return 1;
+ }
+ *ip = addr.s_addr;
+ return 0;
+}
+
+MF_DEFUN(primitive_ismx, NUMBER, STRING domain, STRING ipstr)
+{
+ mxbuf_t mxbuf;
+ mf_status mxstat;
+ unsigned long ip;
+ int rc = 0;
+ int i;
+
+ MF_ASSERT(resolve_host(ipstr, &ip) == 0, mf_noresolve,
+ _("Cannot resolve host name %s"), ipstr);
+
+ mxstat = getmx(domain, mxbuf);
+
+ MF_ASSERT(mxstat == mf_success,
+ mxstat,
+ _("Cannot get MXs for %s"), domain);
+
+ for (i = 0; i < MAXMXCOUNT && mxbuf[i]; i++) {
+ unsigned long n;
+
+ if (!resolve_host(mxbuf[i], &n) && n == ip) {
+ rc = 1;
+ break;
+ }
+ }
+ dns_freemx(mxbuf);
+ MF_RETURN(rc);
+}
+END
+
+MF_DEFUN(relayed, NUMBER, STRING s)
+{
+ MF_RETURN(relayed_domain_p(s));
+}
+END
+
+MF_DEFUN(listens, NUMBER, STRING s, OPTIONAL, NUMBER port)
+{
+ MF_RETURN(listens_on (s, MF_OPTVAL(port, 25)) == mf_success);
+}
+END
+
+MF_DEFUN(domainpart, STRING, STRING str)
+{
+ char *p = strchr(str, '@');
+ MF_RETURN_STRING(p ? p+1 : str);
+}
+END
+
+MF_DEFUN(localpart, STRING, STRING str)
+{
+ char *p = strchr(str, '@');
+
+ if (p) {
+ size_t off;
+ size_t size = p - str;
+ char *string_space = MF_ALLOC_HEAP(off, size + 1);
+ memcpy(string_space, str, size);
+ string_space[size] = 0;
+ MF_RETURN(off);
+ } else
+ MF_RETURN_STRING(str);
+}
+END
+
+MF_INIT

Return to:

Send suggestions and report system problems to the System administrator.