diff src/dnsbl.cpp @ 255:d6d5c50b9278 stable-6-0-30

Allow dnswl_list and dnsbl_list to be empty, to override lists specified in the ancestor contexts. Add daily recipient limits as a multiple of the hourly limits.
author Carl Byington <carl@five-ten-sg.com>
date Mon, 09 Apr 2012 18:02:05 -0700
parents 836b7f2357f9
children d11b529ce9c5
line wrap: on
line diff
--- a/src/dnsbl.cpp	Sun Apr 08 16:17:53 2012 -0700
+++ b/src/dnsbl.cpp	Mon Apr 09 18:02:05 2012 -0700
@@ -114,7 +114,8 @@
 time_t      last_error_time     = 0;
 int         resolver_sock_count = 0;        // protected with fd_pool_mutex
 int         resolver_pool_size  = 0;        // protected with fd_pool_mutex
-rcpt_rates  rcpt_counts;                    // protected with rate_mutex
+rcpt_rates  rcpt_hourly_counts;             // protected with rate_mutex
+rcpt_rates  rcpt_daily_counts;              // protected with rate_mutex
 
 
 struct ns_map {
@@ -163,20 +164,29 @@
 ////////////////////////////////////////////////
 // helper to manipulate recipient counts
 //
-int incr_rcpt_count(const char *user);
-int incr_rcpt_count(const char *user) {
+void incr_rcpt_count(const char *user, int &hourly, int &daily);
+void incr_rcpt_count(const char *user, int &hourly, int &daily) {
     pthread_mutex_lock(&rate_mutex);
-        rcpt_rates::iterator i = rcpt_counts.find(user);
-        int c = 1;
-        if (i == rcpt_counts.end()) {
+        rcpt_rates::iterator i = rcpt_hourly_counts.find(user);
+        hourly = 1;
+        if (i == rcpt_hourly_counts.end()) {
             user = strdup(user);
-            rcpt_counts[user] = c;
+            rcpt_hourly_counts[user] = hourly;
         }
         else {
-            c = ++((*i).second);
+            hourly = ++((*i).second);
+        }
+
+        rcpt_rates::iterator j = rcpt_daily_counts.find(user);
+        daily = 1;
+        if (j == rcpt_daily_counts.end()) {
+            user = strdup(user);
+            rcpt_daily_counts[user] = daily;
+        }
+        else {
+            daily = ++((*j).second);
         }
     pthread_mutex_unlock(&rate_mutex);
-    return c;
 }
 
 ////////////////////////////////////////////////
@@ -1171,14 +1181,16 @@
         return SMFIS_REJECT;
     }
     if (priv.authenticated) {
-        int c = incr_rcpt_count(priv.authenticated);
-        int l = dc.default_context->find_rate(priv.authenticated);
+        int hourly, daily;
+        incr_rcpt_count(priv.authenticated, hourly, daily);
+        int h_limit = dc.default_context->find_rate(priv.authenticated);
+        int d_limit = dc.default_context->get_daily_multiple() * h_limit;
         if (debug_syslog > 1) {
             char msg[maxlen];
-            snprintf(msg, sizeof(msg), "authenticated id %s (%d recipients, %d limit)", priv.authenticated, c, l);
+            snprintf(msg, sizeof(msg), "authenticated id %s (%d %d recipients, %d %d limits)", priv.authenticated, hourly, daily, h_limit, d_limit);
             my_syslog(&priv, msg);
         }
-        if (c > l) {
+        if ((hourly > h_limit) || (daily > d_limit)){
             smfi_setreply(ctx, (char*)"550", (char*)"5.7.1", (char*)"recipient rate limit exceeded");
             return SMFIS_REJECT;
         }
@@ -1525,20 +1537,32 @@
 //
 extern "C" {void* config_loader(void *arg);}
 void* config_loader(void *arg) {
-    int loop = 0;
+    int loop1 = 0;
+    int loop2 = 0;
     while (loader_run) {
         sleep(180);  // look for modifications every 3 minutes
         if (!loader_run) break;
-        loop++;
-        if (loop == 20) {
+        loop1++;
+        loop2++;
+        if (loop1 == 20) {
             // three minutes thru each loop, 20 loops per hour
-            // clear the recipient counts
+            // clear the recipient hourly counts
             pthread_mutex_lock(&rate_mutex);
-                for (rcpt_rates::iterator i=rcpt_counts.begin(); i!=rcpt_counts.end(); i++) {
+                for (rcpt_rates::iterator i=rcpt_hourly_counts.begin(); i!=rcpt_hourly_counts.end(); i++) {
                     (*i).second = 0;
                 }
             pthread_mutex_unlock(&rate_mutex);
-            loop = 0;
+            loop1 = 0;
+        }
+        if (loop2 == 480) {
+            // three minutes thru each loop, 480 loops per day
+            // clear the recipient daily counts
+            pthread_mutex_lock(&rate_mutex);
+                for (rcpt_rates::iterator i=rcpt_daily_counts.begin(); i!=rcpt_daily_counts.end(); i++) {
+                    (*i).second = 0;
+                }
+            pthread_mutex_unlock(&rate_mutex);
+            loop2 = 0;
         }
         CONFIG &dc = *config;
         time_t then = dc.load_time;