diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-03-18 11:09:25 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-03-18 11:09:25 +0000 |
commit | ccef20a48e758594256dbfa246dc6c4bcffc9003 (patch) | |
tree | 3c4ada7f4b3096ef564d8c8ba8dfe8db2002fc81 | |
parent | ec1605d16b925c61f6046760af5eb95e02da2f2a (diff) | |
download | mailfromd-ccef20a48e758594256dbfa246dc6c4bcffc9003.tar.gz mailfromd-ccef20a48e758594256dbfa246dc6c4bcffc9003.tar.bz2 |
* configure.ac, Makefile.am: Add mflib
* NEWS: Update
* mflib: New subdirectory
* mflib/match_dnsbl.mf, mflib/strip_domain_part.mf,
mflib/heloarg_test.mf, mflib/is_ip.mf, mflib/safedb.mf,
mflib/mx.mf, mflib/dns.mf, mflib/revip.mf, mflib/valid_domain.mf,
mflib/match_rhsbl.mf, mflib/spf.mf, mflib/Makefile.am,
mflib/match_cidr.mf: New files
* doc/Makefile.am: Remove extract.awk
* doc/extract.awk: Remove
* doc/mailfromd.texi: Update
* src/symtab.c, src/gram.y, src/mailfromd.h: Implement optional
arguments for user functions
* src/lex.l: Implement #include_once
* src/prog.c (name_destroy): Free the object
* src/bi_ipaddr.m4 (match_cidr): Remove. The function is
implemented in MFL (mflib/match_cidr.mf)
* testsuite/lib/mailfromd.exp, testsuite/etc/cidr.rc,
testsuite/etc/catch.rc, testsuite/etc/catch01.rc,
etc/mailfromd.rc: Use includes when necessary
git-svn-id: file:///svnroot/mailfromd/trunk@1292 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r-- | ChangeLog | 27 | ||||
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | NEWS | 66 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | doc/Makefile.am | 20 | ||||
-rw-r--r-- | doc/extract.awk | 167 | ||||
-rw-r--r-- | doc/mailfromd.texi | 68 | ||||
-rw-r--r-- | etc/mailfromd.rc | 3 | ||||
-rw-r--r-- | mflib/Makefile.am | 32 | ||||
-rw-r--r-- | mflib/dns.mf | 57 | ||||
-rw-r--r-- | mflib/heloarg_test.mf | 127 | ||||
-rw-r--r-- | mflib/is_ip.mf | 34 | ||||
-rw-r--r-- | mflib/match_cidr.mf | 32 | ||||
-rw-r--r-- | mflib/match_dnsbl.mf | 78 | ||||
-rw-r--r-- | mflib/match_rhsbl.mf | 55 | ||||
-rw-r--r-- | mflib/mx.mf | 88 | ||||
-rw-r--r-- | mflib/revip.mf | 34 | ||||
-rw-r--r-- | mflib/safedb.mf | 38 | ||||
-rw-r--r-- | mflib/spf.mf | 122 | ||||
-rw-r--r-- | mflib/strip_domain_part.mf | 40 | ||||
-rw-r--r-- | mflib/valid_domain.mf | 30 | ||||
-rw-r--r-- | src/bi_ipaddr.m4 | 52 | ||||
-rw-r--r-- | src/gram.y | 58 | ||||
-rw-r--r-- | src/lex.l | 57 | ||||
-rw-r--r-- | src/mailfromd.h | 12 | ||||
-rw-r--r-- | src/prog.c | 1 | ||||
-rw-r--r-- | src/symtab.c | 3 | ||||
-rw-r--r-- | testsuite/etc/catch.rc | 3 | ||||
-rw-r--r-- | testsuite/etc/catch01.rc | 5 | ||||
-rw-r--r-- | testsuite/etc/cidr.rc | 4 | ||||
-rw-r--r-- | testsuite/lib/mailfromd.exp | 4 |
31 files changed, 1015 insertions, 307 deletions
@@ -1,3 +1,30 @@ +2007-03-18 Sergey Poznyakoff <gray@gnu.org.ua> + + * configure.ac, Makefile.am: Add mflib + * NEWS: Update + + * mflib: New subdirectory + * mflib/match_dnsbl.mf, mflib/strip_domain_part.mf, + mflib/heloarg_test.mf, mflib/is_ip.mf, mflib/safedb.mf, + mflib/mx.mf, mflib/dns.mf, mflib/revip.mf, mflib/valid_domain.mf, + mflib/match_rhsbl.mf, mflib/spf.mf, mflib/Makefile.am, + mflib/match_cidr.mf: New files + + * doc/Makefile.am: Remove extract.awk + * doc/extract.awk: Remove + * doc/mailfromd.texi: Update + + * src/symtab.c, src/gram.y, src/mailfromd.h: Implement optional + arguments for user functions + * src/lex.l: Implement #include_once + * src/prog.c (name_destroy): Free the object + * src/bi_ipaddr.m4 (match_cidr): Remove. The function is + implemented in MFL (mflib/match_cidr.mf) + + * testsuite/lib/mailfromd.exp, testsuite/etc/cidr.rc, + testsuite/etc/catch.rc, testsuite/etc/catch01.rc, + etc/mailfromd.rc: Use includes when necessary + 2007-03-17 Sergey Poznyakoff <gray@gnu.org.ua> * src/snarf.m4, src/bi_dns.m4, src/bi_dns.m4, src/bi_sa.m4, diff --git a/Makefile.am b/Makefile.am index 357e0cbd..eed87296 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ # This file is part of mailfrom filter. -# Copyright (C) 2005, 2006 Sergey Poznyakoff +# Copyright (C) 2005, 2006, 2007 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 @@ -17,7 +17,7 @@ # MA 02110-1301 USA AUTOMAKE_OPTIONS = gnits 1.8.5 std-options -SUBDIRS = lib gacopyz src etc doc testsuite +SUBDIRS = lib gacopyz src mflib etc doc testsuite ACLOCAL_AMFLAGS = -I m4 distuninstallcheck_listfiles = find . -type f -not -name 'mailfromd.rc' -print @@ -1,4 +1,4 @@ -Mailfromd NEWS -- history of user-visible changes. 2007-03-17 +Mailfromd NEWS -- history of user-visible changes. 2007-03-18 Copyright (C) 2005, 2006, 2007 Sergey Poznyakoff See the end of file for copying conditions. @@ -7,6 +7,39 @@ Please send mailfromd bug reports to <bug-mailfromd@gnu.org.ua> Version 3.1.91, SVN +* Optional arguments in user-defined functions + +User-defined functions can take optional arguments. In declaration, +optional arguments are separated from the mandatory ones by a +semicolon. For example: + + func foo(number a, number b; string c) + +This function is declared with two mandatory arguments (a and b), and +an optional one (c). Subsequently it can be invoked either as + + foo(x, y, z) + +or + + foo(x, y) + +When invoking such functions, any missing arguments are replaced with +default values: + + - 0 for numeric arguments + - "" for string arguments + +Thus, continuing our previous example, the invocation `foo(x, y)' is +equivalent to `foo(x, y, "")'. + +* New statement #include_once + +This statement works exactly like `#include' except that it keeps +track of the included files. If the requested file has already been +included, `#include_once' returns silently, while `#include' issues +an error message. + * Internet address manipulation functions - number ntohl (number N) @@ -18,6 +51,37 @@ Version 3.1.91, SVN - number len_to_netmask (number N) - number netmask_to_len (number N) +* DNS functions + +DNS functions are reemplemented in two layers: + +1. Primitive calls: + +- string primitive_hostname (string IP) +- string primitive_resolve (string S [, string DOMAIN]) +- number primitive_hasmx (string DOMAIN) +- number primitive_ismx (string DOMAIN, string IP) + +These functions throw an exception if the requested lookup operation +fails. + +2. Traditional calls: + +- string hostname (string IP) +- string resolve (string S [, string DOMAIN]) +- number hasmx (string DOMAIN) +- number ismx (string DOMAIN, string IP) + +These are implemented in MFL and work exactly as their predecessors in +3.1.x branch. + +To use the traditional calls, include file "dns.mf". + +* Function `match_cidr' + +This function has been reemplemented in MFL. To use it, include +"match_cidr.mf". + * New statement `throw' The `throw' statement throws the given exception. For example: diff --git a/configure.ac b/configure.ac index a13d9c29..952ddef5 100644 --- a/configure.ac +++ b/configure.ac @@ -453,6 +453,7 @@ AC_CONFIG_FILES([Makefile lib/Makefile gacopyz/Makefile src/Makefile + mflib/Makefile etc/Makefile doc/Makefile testsuite/Makefile diff --git a/doc/Makefile.am b/doc/Makefile.am index 3ff44f15..07c4b9ba 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,5 +1,5 @@ # This file is part of mailfrom filter. -# Copyright (C) 2005, 2006 Sergey Poznyakoff +# Copyright (C) 2005, 2006, 2007 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 @@ -27,7 +27,6 @@ mailfromd_TEXINFOS=\ EXTRA_DIST = \ check-docs.sh\ - extract.awk\ gendocs_template\ mastermenu.el\ untabify.el @@ -131,20 +130,3 @@ manual: TEXI2DVI="$(TEXI2DVI) -t @finalout" \ $(GENDOCS) $(PACKAGE) '$(PACKAGE_NAME) manual' -extract: - @echo "${SELECT}" > sel.tmp; \ - while [ -s sel.tmp ]; \ - do \ - s=`cat sel.tmp | tr '\n' ','`; \ - rm sel.tmp; \ - ${AWK} -vSELECT=$$s \ - -f ${top_srcdir}/doc/extract.awk ${info_TEXINFOS} | \ - while read word rest; \ - do \ - if [ $$word = "Require" ]; then \ - echo "$$rest" >> sel.tmp; \ - else \ - echo $$word $$rest; \ - fi; \ - done; \ - done diff --git a/doc/extract.awk b/doc/extract.awk deleted file mode 100644 index 63996214..00000000 --- a/doc/extract.awk +++ /dev/null @@ -1,167 +0,0 @@ -# This file is part of mailfrom filter. -# 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 - -BEGIN { - if (SELECT) { - gsub(/,$/,"", SELECT) - n = split(SELECT, a, ",") - for (i = 1; i <= n; i++) - select[a[i]] = 1 - } -} - -function error(s) -{ - print "extract.awk: " ARGV[1] ":" NR ": " s > "/dev/stderr" -} - -function output(file, s) -{ - if (!notified) { - print "Creating file `" file "'" - notified = 1 - } - print s > file -} - -function sprintf_multitab(s, a, n, i, r) -{ - sub(/@(head)?item/, "", s) - n = split(s, a, /@tab/) - r = "" - for (i = 1; i <= n; i++) - r = r "" sprintf("%-*s", multitable[i-1], a[i]) - return r -} - -function flush_mtline( s) -{ - if (match(mtline, "@headitem")) { - s = sprintf_multitab(mtline) - output(file, "# " s) - gsub(/./, "-", s) - output(file, "# " s) - } else - output(file, "# " sprintf_multitab(mtline)) -} - -state == 0 && /^@deftypefn[ \t]+{Sample[ \t]+Function}/ { - name = $5 - if (SELECT && !select[name]) - next - file = name ".mf" - notified = 0 - state = 1 - if (match($0, ".*@$")) { - save0 = substr($0, 1, length($0)-1) - while (getline > 0 && match($0, ".*@$")) - save0 = save0 substr($0, 1, length($0)-1) - $0 = save0 $0 - } -} - -state == 0 { next } - -/@end[ \t]+deftypefn/ { - close(file) - state = 0 - next -} - -state == 1 && /^[ \t]*@smallexample/ { state = 2; next } -state == 2 && /^@end[ \t]+smallexample/ { state = 1; next } -state == 2 && /#include/ { - s = $2 - gsub(/[<>\"]/,"",s) - gsub(/\.mf$/,"",s) - if (SELECT && !select[s]) - print "Require " s -} - -state == 1 && /^[ \t]*@table/ { state = 3; table = $2; next } -state == 3 && /^@end[ \t]+table/ { state = 1; next } - -state == 1 && /^[ \t]*@multitable/ { - state = 6; - delete multitable - mtcount = 0 - for (i = 3; i <= NF; i++) - multitable[mtcount++] = $i * 78 - next -} -state == 6 && /^@end[ \t]+multitable/ { flush_mtline(); state = 1; next } - -# Parse texinfo commands: - -/^[ \t]*@c[ \t]/ { next } -/^[ \t]*@comment[ \t]/ { next } -/^[ \t]*@ignore/ { oldstate = state; state = 4; next } -state == 4 && /^[ \t]*@end ignore/ { state = oldstate; next } - -/^[ \t]*@example-output/ { oldstate = state; state = 5; next } -state == 5 && /^}$/ { state = oldstate; next } - -state == 3 && /^@itemx*/ { - if (table == "@samp") - output(file, "# `" $2 "'") - if (table == "@var") - output(file, "# " toupper($2) ) - else - output(file, "# " $2) - next -} - -# Remove texinfo markers -{ - gsub(/@{/, "{") - gsub(/@}/, "}") - gsub(/@result{}/, "=>") - $0 = gensub(/@samp{([^}]*)}/, "`\\1'", "g") - while (match($0, "@var{[^}]*}")) { - $0 = substr($0, 1, RSTART-1) \ - toupper(substr($0, RSTART+5, RLENGTH-6)) \ - substr($0, RSTART+RLENGTH) - } - $0 = gensub(/@[a-z]+{([^}]*)}/, "\\1", "g") -} - -/^@deftypefn[ \t]+{Sample[ \t]+Function}/ { - s = "" - for (i = 4; i <= NF; i++) - s = s " " $i - $0 = s -} - -state == 6 && /@item/ { flush_mtline(); mtline = $0; next } -state == 6 && /@headitem/ { flush_mtline(); mtline = $0; next } -state == 6 { mtline = mtline " " $0; next } - -# Remove any leftover commands -/^[ \t]*@.*/ { next } - -state == 3 || state == 5 { - output(file, "# " $0) - next -} - -{ - if (state == 1) - output(file, "# " $0) - else - output(file, $0) -} diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi index 11890f79..2190cb65 100644 --- a/doc/mailfromd.texi +++ b/doc/mailfromd.texi @@ -735,12 +735,34 @@ steps: your startup file: @smallexample -#include <status.mfh> +#include_once <status.mfh> @end smallexample @item Remove all instances of @samp{&} in front of the constants. You can use the following @command{sed} expression: @samp{s/&\([a-z]\)/\1/g}. + +@item + If your code uses any of the following functions: @code{hostname}, +@code{resolve}, @code{hasmx} or @code{ismx}, add the following line +to the top of your script: + +@smallexample +#include_once <dns.mf> +@end smallexample + +@FIXME-xref{} + +@item + If your code uses function @code{match_cidr}, add the following line +to the top of your script: + +@smallexample +#include_once <match_cidr.mf> +@end smallexample + +@FIXME-xref{} + @end enumerate @node 30x-31x @@ -4189,6 +4211,7 @@ inet_ntoa(2130706433) @result{} "127.0.0.1" @deftypefn {Built-in Function} boolean match_cidr (string @var{ip}, @ string @var{cidr}) +@FIXME{Include @file{match_cidr.mf}} Returns @code{true} if the IP address @var{ip} pertains to the IP range @var{cidr}. The first argument, @var{ip}, is a string representation of an IP address. The second argument, @var{cidr}, is @@ -4212,6 +4235,11 @@ fi @node DNS functions @subsubsection DNS Functions +@UNREVISED{} + +@FIXME{The functions are reimplemented in two layers. Instruct how +to use upper-level functions (@code{#include_once <dns.mf>}), and +describe lower-level ones.} All DNS-related functions cache their results in the database @samp{dns}, so no matter how many times you use a particular function @@ -4276,7 +4304,7 @@ equivalent: @smallexample hostname("213.130.0.22") -resolve("22.0.120.213", "in-addr.arpa") +resolve("22.0.130.213", "in-addr.arpa") @end smallexample This makes it possible to use @code{resolve} for querying DNS black @@ -5196,6 +5224,7 @@ done @node Some Useful Functions @subsubsection Some Useful Functions +@UNREVISED{} This subsection introduces several functions that can be useful in your scripts. It can serve both as an example of writing @@ -5203,39 +5232,8 @@ user-defined functions and as a repository of such functions (until @command{mailfromd} has a library facility, which is planned for one of the next releases). -@cindex make extract -@cindex extract, @command{make} command -@cindex extract.awk - To extract any of these functions into files suitable for inclusion -in you @command{mailfromd} configuration, change to the directory -@file{/doc} of the distribution and run @kbd{make extract}. By -default, it will extract all functions into separate files. The names -of the created files will be printed on the standard output: - -@smallexample -@group -$ @kbd{make extract} -Creating file `revip.mf' -Creating file `strip_domain_part.mf' -Creating file `match_dnsbl.mf' -Creating file `match_rhsbl.mf' -@end group -@end smallexample - - If you wish to extract only selected functions, type the -comma-separated list of their names in the variable @code{SELECT}, -for example: - -@smallexample -@group -$ @kbd{make extract SELECT=revip,match_dnsbl} -Creating file `revip.mf' -Creating file `match_dnsbl.mf' -@end group -@end smallexample - - Use the @code{#include} statement to include the extracted files -in your filter script (@pxref{include}). +@FIXME{The functions are located in @file{mflib/}. Instruct how to use +them}. @anchor{revip} @deftypefn {Sample Function} string revip (string @var{ip}) diff --git a/etc/mailfromd.rc b/etc/mailfromd.rc index e1fd35e8..045b0582 100644 --- a/etc/mailfromd.rc +++ b/etc/mailfromd.rc @@ -24,7 +24,8 @@ #pragma regex +extended +icase #pragma option debug 1 -#include <status.mfh> +#include_once <status.mfh> +#include_once <dns.mf> set mailfrom_address "<>" set ehlo_domain "your.domain" diff --git a/mflib/Makefile.am b/mflib/Makefile.am new file mode 100644 index 00000000..75bb1ece --- /dev/null +++ b/mflib/Makefile.am @@ -0,0 +1,32 @@ +# This file is part of mailfromd. +# Copyright (C) 2007 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 + +incdir=$(pkgdatadir)/$(VERSION)/include +inc_DATA =\ + dns.mf\ + heloarg_test.mf\ + is_ip.mf\ + match_cidr.mf\ + match_dnsbl.mf\ + match_rhsbl.mf\ + mx.mf\ + revip.mf\ + safedb.mf\ + spf.mf\ + strip_domain_part.mf\ + valid_domain.mf diff --git a/mflib/dns.mf b/mflib/dns.mf new file mode 100644 index 00000000..00dcdc58 --- /dev/null +++ b/mflib/dns.mf @@ -0,0 +1,57 @@ +/* User-level DNS functions + Copyright (C) 2007 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 */ + +func hostname (string ipstr) returns string +do + catch * + do + return %ipstr + done + return primitive_hostname(%ipstr) +done + +func resolve (string str; string domain) returns string +do + catch * + do + return "0" + done + if %domain == "" + return primitive_resolve (%str) + else + return primitive_resolve (%str, %domain) + fi +done + +func hasmx (string str) returns string +do + catch * + do + return 0 + done + return primitive_hasmx(%str) +done + +func ismx (string domain, string ipstr) returns number +do + catch * + do + return 0 + done + return primitive_ismx (%domain, %ipstr) +done diff --git a/mflib/heloarg_test.mf b/mflib/heloarg_test.mf new file mode 100644 index 00000000..80b713eb --- /dev/null +++ b/mflib/heloarg_test.mf @@ -0,0 +1,127 @@ +/* HELO consistency checker + Copyright (C) 2006, 2007 Jan Rafaj + + 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 */ + +# number heloarg_test (string ARG, string REMOTE_IP, string LOCAL_IP) +# +# Verify if an argument of `HELO' (`EHLO') command is +# valid. Arguments: +# +# ARG +# `HELO' (`EHLO') argument. Typically, the value of $s +# Sendmail macro; +# +# REMOTE_IP +# IP address of the remote clinet. Typically, the value of +# $client_addr Sendmail macro; +# +# LOCAL_IP +# IP address of this SMTP server; +# +# If ARG passes all tests, the function returns `0'. +# Otherwise it returns a numeric error code. Increasing error codes +# correspond to increased strictness level of the performed check, as +# shown in the table below: +# +# +# Code Meaning +# --------------------------------------------------------------------- +# 1 ARG is our IP address. +# 2 ARG is an IP, but it does not match the remote party IP address. +# 3 ARG is an IP, but it does not resolve. +# 4 ARG is in square brackets, but it is not an IP address. +# 5 ARG is not an IP address and does not resolve to one. +# 6 ARG resolves to our server IP. +# 7 ARG does not resolve to the remote client IP address, +# +#pragma regex +extended +#include_once "is_ip.mf" +#include_once "dns.mf" + +const HELO_SUCCESS 0 +const HELO_MYIP 1 # ARG is our IP address. +const HELO_IPNOMATCH 2 # ARG is an IP, but it does not match the remote + # party IP address. +const HELO_ARGNORESOLVE 3 # ARG is an IP, but it does not resolve. +const HELO_ARGNOIP 4 # ARG is in square brackets, but it is not an + # IP address. +const HELO_ARGINVALID 5 # ARG is not an IP address and does not resolve + # to one. +const HELO_MYSERVERIP 6 # ARG resolves to our server IP. +const HELO_IPMISMATCH 7 # ARG does not resolve to the remote client + # IP address, + +func domainof(string arg) returns string +do + if %arg matches '[^.]+\.(.*)' + return \1 + else + return %arg + fi +done + +func heloarg_test(string arg, string remote_ip, string local_ip) + returns number +do + string helo_arg + number heloarg_must_be_ip + + set helo_arg %arg + set heloarg_must_be_ip 0 + + if %arg matches '^\[(.*)\]$' + set helo_arg "\1" + set heloarg_must_be_ip 1 + fi + + if is_ip (%helo_arg) + if (%helo_arg = %local_ip and %local_ip != %remote_ip) + # `HELO' arg may not be this server's IP + return HELO_MYIP + elif %helo_arg != %remote_ip + # `HELO' arg does not match remote server's IP + return HELO_IPNOMATCH + elif (%heloarg_must_be_ip = 0 + and hostname %helo_arg = %helo_arg) + # `HELO' arg not in brackets and doesnt resolve + return HELO_ARGNORESOLVE + else + return HELO_SUCCESS + fi + elif %heloarg_must_be_ip = 1 + # `HELO' arg in brackets is not an IP + return HELO_ARGNOIP + elif ismx(%helo_arg, %remote_ip) + or domainof(hostname(%remote_ip)) = %helo_arg + return HELO_SUCCESS + elif (resolve %helo_arg = "0") + # `HELO' arg does not resolve to an IP + return HELO_ARGINVALID + elif (%helo_arg = hostname %local_ip + and %local_ip != %remote_ip) + # `HELO' arg may not be this server's hostname + return HELO_MYSERVERIP + elif (resolve %helo_arg != %remote_ip + and hostname %remote_ip != %helo_arg) + # `HELO' arg does not resolve to remote server's IP nor to its + # domain + return HELO_IPMISMATCH + else + return HELO_SUCCESS + fi +done + diff --git a/mflib/is_ip.mf b/mflib/is_ip.mf new file mode 100644 index 00000000..9684be39 --- /dev/null +++ b/mflib/is_ip.mf @@ -0,0 +1,34 @@ +/* IP validity checker. + Copyright (C) 2006, 2007 Jan Rafaj + + 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 */ + +# boolean is_ip (string STR) +# +# Returns `true' if STR is a valid IPv4 address. For +# example: +# +# is_ip("1.2.3.4") => 1 +# is_ip("1.2.3.x") => 0 +# is_ip("blah") => 0 +# is_ip("255.255.255.255") => 1 +# is_ip("0.0.0.0") => 1 +# +#pragma regex +extended +func is_ip(string ip) returns number +do + return %ip matches '^([0-9]{1,3}\.){3}[0-9]{1,3}$' +done diff --git a/mflib/match_cidr.mf b/mflib/match_cidr.mf new file mode 100644 index 00000000..94541c26 --- /dev/null +++ b/mflib/match_cidr.mf @@ -0,0 +1,32 @@ +/* Implementation of match_cidr call + Copyright (C) 2007 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_once "status.mfh" +#pragma regex +extended + +func match_cidr(string ipstr, string cidr) returns number +do + number netmask + + if %cidr matches '^(([0-9]{1,3}\.){3}[0-9]{1,3})/([0-9][0-9]?)' + return inet_aton(%ipstr) & len_to_netmask(\3) = inet_aton(\1) + else + throw invcidr "invalid CIDR (%cidr)" + fi + return 0 +done |