/* This file is part of mailfrom filter. -*- c -*- Copyright (C) 2006 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 2, 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include MF_DEFUN(hostname, STRING, STRING string) { char *s = env_dict_getsym(env, string); if (!s) { char hbuf[NI_MAXHOST]; if (resolve_ipstr(string, hbuf, sizeof(hbuf))) hbuf[0] = 0; s = env_dict_install(env, string, hbuf); } if (s[0] == 0) s = string; push(env, s); } END MF_DEFUN(resolve, STRING, STRING string) { char *s; struct hostent *host; s = env_dict_getsym(env, string); if (!s) { host = gethostbyname(string); if (!host) s = "0"; else if (host->h_length == 4) { struct in_addr addr; addr.s_addr = *(unsigned long*)host->h_addr; s = inet_ntoa(addr); } else s = "resolved"; s = env_dict_install(env, string, s); } push(env, s); } END MF_DEFUN(hasmx, NUMBER, STRING string) { mxbuf_t mxbuf; mf_status mxstat; mxstat = getmx(string, mxbuf); if (mxstat != mf_success) { if (env_catch(env, mxstat) == 0) return; } else freemx(mxbuf); push(env, (STKVAL)(mxstat == mf_success)); } END static int resolve_host(const char *string, unsigned long *ip) { struct hostent *host = gethostbyname(string); if (!host) return 1; else if (host->h_length == 4) { *ip = *(unsigned long*)host->h_addr; return 0; } return 1; } MF_DEFUN(ismx, NUMBER, STRING domain, STRING ipstr) { mxbuf_t mxbuf; mf_status mxstat; unsigned long ip; int rc = 0; if (resolve_host(ipstr, &ip)) { if (env_catch(env, mf_resolve) == 0) return; runtime_error(env, "cannot resolve host name %s", ipstr); } mxstat = getmx(domain, mxbuf); if (mxstat != mf_success) { if (env_catch(env, mxstat) == 0) return; } else { int i; for (i = 0; i < MAXMXCOUNT && mxbuf[i]; i++) { unsigned long n; if (!resolve_host(mxbuf[i], &n) && n == ip) { rc = 1; break; } } freemx(mxbuf); } push(env, (STKVAL) rc); } END MF_DEFUN(relayed, NUMBER, STRING s) { push(env, (STKVAL) relayed_domain_p(s)); } END MF_DEFUN(listens, NUMBER, STRING s) { push(env, (STKVAL)(listens_on (s, 25) == mf_success)); } END MF_DEFUN(match_cidr, NUMBER, STRING ipstr, STRING cidrstr) { char *p; struct in_addr addr, cidr; char netbuf[16], *netstr; unsigned long netmask; int result = 0; const struct locus *locus = env_get_locus(env); do { if (inet_aton(ipstr, &addr) == 0) { if (env_catch(env, mf_invip) == 0) return; runtime_error(env, "invalid IP address (%s)", ipstr); } p = strchr(cidrstr, '/'); if (!p) { netstr = cidrstr; netmask = 0xfffffffful; } else { size_t len = p - cidrstr; unsigned long n; if (len >= sizeof netbuf) { if (env_catch(env, mf_invcidr) == 0) return; runtime_error(env, "invalid CIDR (%s)", cidrstr); } memcpy(netbuf, cidrstr, len); netbuf[len] = 0; netstr = netbuf; n = strtoul(p + 1, &p, 10); if (*p || n > 32) { if (env_catch(env, mf_invcidr) == 0) return; runtime_error(env, "invalid CIDR (netmask of %s)", cidrstr); } n = 32 - n; if (n == 32) netmask = 0; else netmask = (0xfffffffful >> n) << n; } if (inet_aton(netstr, &cidr) == 0) { if (env_catch(env, mf_invcidr) == 0) return; runtime_warning(env, "invalid CIDR (network part of %s)", cidrstr); break; } addr.s_addr = ntohl(addr.s_addr); cidr.s_addr = ntohl(cidr.s_addr); debug5(100, "%s:%lu: addr=%lx net=%lx mask=%lx" , locus->file, locus->line, addr.s_addr, cidr.s_addr, netmask); result = (addr.s_addr & netmask) == cidr.s_addr; } while (0); push(env, (STKVAL) result); } END MF_DEFUN(domainpart, STRING, STRING str) { char *p = strchr(str, '@'); pushs(env, p ? p+1 : str); } END MF_DEFUN(localpart, STRING, STRING str) { char *p = strchr(str, '@'); if (p) { size_t size = p - str; char *string_space = heap_reserve(env, size); memcpy(string_space, str, size); string_space[size] = 0; push(env, string_space); } else pushs(env, str); } END MF_INIT(dns)