diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-09-11 12:16:53 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-09-11 12:16:53 +0000 |
commit | 0434e04c026bc4014a59eb7b9af5611a0df5fc9e (patch) | |
tree | c0ef6e191c3b98c25c0412ddb979627988a54ec6 | |
parent | a5e06ce6cbbc41a806857055bb689bdce4d39b57 (diff) | |
download | mailfromd-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-- | ChangeLog | 11 | ||||
-rw-r--r-- | NEWS | 17 | ||||
-rw-r--r-- | doc/mailfromd.texi | 24 | ||||
-rw-r--r-- | src/bi_other.m4 | 4 | ||||
-rw-r--r-- | src/mailfromd.h | 2 | ||||
-rw-r--r-- | src/mtasim.c | 46 | ||||
-rw-r--r-- | src/mu_dbm.c | 4 | ||||
-rw-r--r-- | src/rate.c | 4 |
8 files changed, 93 insertions, 19 deletions
@@ -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 @@ -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 @@ -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; |