aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-09-11 12:16:53 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-09-11 12:16:53 +0000
commit0434e04c026bc4014a59eb7b9af5611a0df5fc9e (patch)
treec0ef6e191c3b98c25c0412ddb979627988a54ec6
parenta5e06ce6cbbc41a806857055bb689bdce4d39b57 (diff)
downloadmailfromd-0434e04c026bc4014a59eb7b9af5611a0df5fc9e.tar.gz
mailfromd-0434e04c026bc4014a59eb7b9af5611a0df5fc9e.tar.bz2
* src/mu_dbm.c [WITH_GDBM] (mu_dbm_firstkey,mu_dbm_nextkey):
Return MU_ERR_NOENT instead of MU_ERR_FAILURE. * src/mailfromd.h (get_rate): New argument mincount * src/rate.c: Likewise * src/bi_other.m4 (rate): Optional argument mincnt * src/mtasim.c: Accept MAIL FROM: and RCPT TO: without extra space after `:'. * doc/mailfromd.texi, NEWS: Update git-svn-id: file:///svnroot/mailfromd/trunk@1509 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r--ChangeLog11
-rw-r--r--NEWS17
-rw-r--r--doc/mailfromd.texi24
-rw-r--r--src/bi_other.m44
-rw-r--r--src/mailfromd.h2
-rw-r--r--src/mtasim.c46
-rw-r--r--src/mu_dbm.c4
-rw-r--r--src/rate.c4
8 files changed, 93 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 726917ae..33514920 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2007-09-11 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * src/mu_dbm.c [WITH_GDBM] (mu_dbm_firstkey,mu_dbm_nextkey):
+ Return MU_ERR_NOENT instead of MU_ERR_FAILURE.
+ * src/mailfromd.h (get_rate): New argument mincount
+ * src/rate.c: Likewise
+ * src/bi_other.m4 (rate): Optional argument mincnt
+ * src/mtasim.c: Accept MAIL FROM: and RCPT TO: without extra space
+ after `:'.
+ * doc/mailfromd.texi, NEWS: Update
+
2007-09-03 Sergey Poznyakoff <gray@gnu.org.ua>
* src/dnsbase.c (dns_resolve_hostname): Make name buffer big
diff --git a/NEWS b/NEWS
index 103d7779..fba2e9ff 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-Mailfromd NEWS -- history of user-visible changes. 2007-08-09
+Mailfromd NEWS -- history of user-visible changes. 2007-09-11
Copyright (C) 2005, 2006, 2007 Sergey Poznyakoff
See the end of file for copying conditions.
@@ -10,7 +10,7 @@ Version 4.1.1 (SVN)
* Licensed under the GPLv3
* Syslog-async code has been withdrawn, due to its incompatibility with
-the new license. The similar functionality will probably be introduced
+the new license. The similar functionality will probably be introduced
again when I write it.
* RFC 2821 compatibility
@@ -18,9 +18,20 @@ again when I write it.
The sender verification engine used to send whitespace character
between `MAIL FROM:' and `RCPT TO:' commands and their argument.
This violated RFC 2821, which requires the argument to follow the
-command without any intermediate whitespace. It is fixed in this
+command without any intermediate whitespace. It is fixed in this
release.
+* Sample threshold for `rate' function.
+
+The `rate' function takes an optional third argument allowing to
+specify the minimum number of received mails needed to obtain
+sending rate value. The default is 2, which is probably too
+conservative. The following example raises it to 10:
+
+ if rate($f "-" ${client_addr}, interval("1 hour"), 10) > %maxrate
+ ...
+ fi
+
Version 4.1, 2007-06-11
diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi
index 1043082f..078f722a 100644
--- a/doc/mailfromd.texi
+++ b/doc/mailfromd.texi
@@ -2198,10 +2198,24 @@ this function, the function invocation would be:
rate($f "-" $@{client_addr@}, interval("1 hour"))
@end smallexample
- For more information about @code{rate} function, see @ref{rate}. The
-@code{interval} function is described in @ref{interval} and time
+ The @code{interval} function is described in @ref{interval}, and time
intervals are discussed in @ref{time interval specification}.
+ The @code{rate} function begins returning non-zero value as soon as
+it has enough data to compute the rate. By default, it needs at least
+two mails. Since this may lead to a big number of false positives
+(i.e. overestimated rates) at the beginning of sampling interval,
+there is a way to specify a minimum number of samples @code{rate} must
+collect before starting to actually compute rates. This number of
+samples is given as the optional third argument to the function. For
+example, the following call will return 0 unless at least 10 mails
+with the given key value were detected:
+
+@smallexample
+ rate($f "-" $@{client_addr@}, interval("1 hour"), 10)
+@end smallexample
+
+For additional information about @code{rate} function, see @ref{rate}.
@node Greylisting
@section Greylisting
@@ -6581,10 +6595,12 @@ explanation.
@anchor{rate}
@deftypefn {Built-in Function} number rate (string @var{key}, @
- number @var{sample-interval})
+ number @var{sample-interval}, [number @var{threshold}])
Returns the mail sending rate for @var{key} per
-@var{sample-interval}. @xref{Sending Rate}, for a detailed
+@var{sample-interval}. Optional @var{threshold}, if supplied,
+specifies the minimal number of mails needed to obtain the
+statistics. The default is 2. @xref{Sending Rate}, for a detailed
discussion.
@end deftypefn
diff --git a/src/bi_other.m4 b/src/bi_other.m4
index 7d1ec7e4..d9a51db8 100644
--- a/src/bi_other.m4
+++ b/src/bi_other.m4
@@ -72,12 +72,12 @@ MF_DEFUN(interval, NUMBER, STRING str)
}
END
-MF_DEFUN(rate, NUMBER, STRING key, NUMBER interval)
+MF_DEFUN(rate, NUMBER, STRING key, NUMBER interval, OPTIONAL, NUMBER mincnt)
{
double rate;
long lrate;
- MF_ASSERT(get_rate(key, &rate) == mf_success,
+ MF_ASSERT(get_rate(key, &rate, MF_OPTVAL(mincnt)) == mf_success,
mf_dbfailure,
_("Cannot get rate for %s"), key);
lrate = rate * interval;
diff --git a/src/mailfromd.h b/src/mailfromd.h
index 2f6c5a53..7ce0f898 100644
--- a/src/mailfromd.h
+++ b/src/mailfromd.h
@@ -861,7 +861,7 @@ mf_status dns_cache_get(int type, const char *keystr, char **rbuf,
void dns_cache_put(int type, const char *keystr, time_t ttl, char **rbuf,
size_t rcnt);
-mf_status get_rate(char *email, double *ret);
+mf_status get_rate(char *email, double *ret, size_t mincount);
int db_list_item(char *dbname, char *key, db_item_printer_t fun);
int db_list(char *dbname, db_item_printer_t fun);
diff --git a/src/mtasim.c b/src/mtasim.c
index 94f53e1f..debdc13f 100644
--- a/src/mtasim.c
+++ b/src/mtasim.c
@@ -1463,12 +1463,48 @@ process_data_reply (char *sname, char *arg, int rc, int *state, char **reply)
return 0;
}
+/* Check if (*PARGV)[1] begins with the string PFX, followed by ':'.
+ Return 0 if so, 1 otherwise.
+ If any characters follow the semicolon, reformat *PARGV so that
+ [1] contains only PFX:, [2] contains the characters in question,
+ and the rest of entries after [2] is properly reindexed.
+*/
+int
+check_address_command(const char *pfx, int *pargc, char ***pargv)
+{
+ int argc = *pargc;
+ char **argv = *pargv;
+ int pfxlen = strlen (pfx);
+ int arglen = strlen (argv[1]);
+
+ if (argc >= 2 && arglen > pfxlen
+ && strncasecmp (argv[1], pfx, pfxlen) == 0
+ && argv[1][pfxlen] == ':') {
+
+ if (arglen > pfxlen + 1)
+ {
+ argc++;
+ argv = xrealloc (argv, (argc + 1) * sizeof (argv[0]));
+ memmove (&argv[2], &argv[1], (argc - 1) * sizeof argv[1]);
+ argv[2] = xstrdup (argv[1] + pfxlen + 1);
+ argv[1][pfxlen + 1] = 0;
+
+ *pargc = argc;
+ *pargv = argv;
+ }
+
+ return 0;
+ }
+ return 1;
+}
+
static void
-smtp_rcpt (int argc, char **argv, int *state)
+smtp_rcpt (int *pargc, char ***pargv, int *state)
{
nrcpt++;
- if (argc == 3 && strcasecmp (argv[1], "to:") == 0)
+ if (check_address_command("to", pargc, pargv) == 0)
{
+ char **argv = *pargv;
int rc;
char *sender;
char *addr;
@@ -1674,7 +1710,7 @@ smtp (void)
break;
case KW_MAIL:
- if (argc == 3 && strcasecmp (argv[1], "from:") == 0)
+ if (check_address_command("from", &argc, &argv) == 0)
{
int rc;
char *sender;
@@ -1741,7 +1777,7 @@ smtp (void)
break;
case KW_RCPT:
- smtp_rcpt (argc, argv, &state);
+ smtp_rcpt (&argc, &argv, &state);
break;
default:
@@ -1752,7 +1788,7 @@ smtp (void)
case STATE_RCPT:
switch (kw) {
case KW_RCPT:
- smtp_rcpt (argc, argv, &state);
+ smtp_rcpt (&argc, &argv, &state);
break;
case KW_DATA:
diff --git a/src/mu_dbm.c b/src/mu_dbm.c
index 9ee87655..f736bc94 100644
--- a/src/mu_dbm.c
+++ b/src/mu_dbm.c
@@ -185,14 +185,14 @@ int
mu_dbm_firstkey (DBM_FILE *db, DBM_DATUM *pkey)
{
*pkey = gdbm_firstkey (db->db);
- return (pkey->dptr == NULL) ? MU_ERR_FAILURE : 0;
+ return (pkey->dptr == NULL) ? MU_ERR_NOENT : 0;
}
int
mu_dbm_nextkey (DBM_FILE *db, DBM_DATUM prevkey, DBM_DATUM *pkey)
{
*pkey = gdbm_nextkey (db->db, prevkey);
- return (pkey->dptr == NULL) ? MU_ERR_FAILURE : 0;
+ return (pkey->dptr == NULL) ? MU_ERR_NOENT : 0;
}
void
diff --git a/src/rate.c b/src/rate.c
index a4fbc42e..43e5430b 100644
--- a/src/rate.c
+++ b/src/rate.c
@@ -30,7 +30,7 @@ struct rate_result {
};
mf_status
-get_rate(char *email, double *ret)
+get_rate(char *email, double *ret, size_t mincount)
{
DBM_FILE db;
DBM_DATUM key;
@@ -78,7 +78,7 @@ get_rate(char *email, double *ret)
rp->timestamp = t;
rp->count++;
- if (rp->interval == 0)
+ if (rp->interval == 0 || rp->count < mincount)
result = 0;
else
result = (double) rp->count / rp->interval;

Return to:

Send suggestions and report system problems to the System administrator.