diff src/dnsbl.cpp @ 44:6b79046b18c2

changes for 3.2
author carl
date Fri, 09 Jul 2004 07:53:02 -0700
parents acbe44bbba22
children 66c66a6ee65f
line wrap: on
line diff
--- a/src/dnsbl.cpp	Mon Jul 05 22:24:22 2004 -0700
+++ b/src/dnsbl.cpp	Fri Jul 09 07:53:02 2004 -0700
@@ -116,6 +116,7 @@
 typedef map<char *, DNSBLP, ltstr>        dnsblp_map;
 typedef map<char *, DNSBLLP, ltstr>       dnsbllp_map;
 typedef set<char *, ltstr>                string_set;
+typedef set<int>                          int_set;
 typedef list<char *>                      string_list;
 typedef map<char *, int, ltstr>           ns_map;
 
@@ -135,6 +136,7 @@
     char *      content_message;    // ""
     char *      host_limit_message; // error message for excessive host names
     int         host_limit;         // limit on host names
+    bool        host_random;        // pick a random selection of host names rather than error for excessive hosts
     char *      tag_limit_message;  // error message for excessive bad html tags
     int         tag_limit;          // limit on bad html tags
     string_set  html_tags;          // set of valid html tags
@@ -150,6 +152,7 @@
     content_message    = NULL;
     host_limit_message = NULL;
     host_limit         = 0;
+    host_random        = false;
     tag_limit_message  = NULL;
     tag_limit          = 0;
 }
@@ -586,17 +589,30 @@
     if (!dc.content_suffix) return oksofar;
     int count = 0;
     ns_map nameservers;
-    int lim = priv.pc->host_limit;
+    bool ran = priv.pc->host_random;
+    int  lim = priv.pc->host_limit;         // we should not look at more than this many hosts
+    int  cnt = priv.memory->hosts.size();   // number of hosts we could look at
+    int_set ips;    // remove duplicate ip addresses
     for (string_set::iterator i=priv.memory->hosts.begin(); i!=priv.memory->hosts.end(); i++) {
+        host = *i;  // a reference into priv.memory->hosts, which will live until this smtp transaction is closed
+        if ((cnt > lim) && (lim > 0) && ran) {
+            // try to only look at lim/cnt fraction of the available cnt host names
+            int r = rand() % cnt;
+            if (r >= lim) {
+                char buf[1000];
+                snprintf(buf, sizeof(buf), "host %s skipped", host);
+                my_syslog(&priv, buf);
+                continue;
+            }
+        }
         count++;
-        if ((count > lim) && (lim > 0)) {
+        if ((count > lim) && (lim > 0) && (!ran)) {
             discard(nameservers);
             return reject_host;
         }
-        host = *i;  // a reference into priv.memory->hosts, which will live until this smtp transaction is closed
         ip   = protected_dns_interface(host, true, &nameservers);
         if (debug_syslog) {
-            char buf[200];
+            char buf[1000];
             if (ip) {
                 char adr[sizeof "255.255.255.255"];
                 adr[0] = '\0';
@@ -609,6 +625,9 @@
             my_syslog(&priv, buf);
         }
         if (ip) {
+            int_set::iterator i = ips.find(ip);
+            if (i == ips.end()) {
+                ips.insert(ip);
             status st = check_single(ip, dc.content_suffix);
             if (st == reject) {
                 discard(nameservers);
@@ -616,10 +635,12 @@
             }
         }
     }
+    }
     lim *= 4;   // allow average of 3 ns per host name
     for (ns_map::iterator i=nameservers.begin(); i!=nameservers.end(); i++) {
         count++;
         if ((count > lim) && (lim > 0)) {
+            if (ran) continue; // don't complain
             discard(nameservers);
             return reject_host;
         }
@@ -640,6 +661,9 @@
             my_syslog(&priv, buf);
         }
         if (ip) {
+            int_set::iterator i = ips.find(ip);
+            if (i == ips.end()) {
+                ips.insert(ip);
             status st = check_single(ip, dc.content_suffix);
             if (st == reject) {
                 host = register_string(priv.memory->hosts, host);   // put a copy into priv.memory->hosts, and return that reference
@@ -648,6 +672,7 @@
             }
         }
     }
+    }
     discard(nameservers);
     host = NULL;
     int bin = priv.memory->binary_tags;
@@ -884,6 +909,9 @@
     if (dc.host_limit) {
         fprintf(stdout, "\ncontent filtering for host names enabled with limit %d %s\n", dc.host_limit, dc.host_limit_message);
     }
+    if (dc.host_random) {
+        fprintf(stdout, "\nrandom selection of host names, host limit message is not used\n");
+    }
     if (dc.tag_limit) {
         fprintf(stdout, "\ncontent filtering for excessive html tags enabled with limit %d %s\n", dc.tag_limit, dc.tag_limit_message);
     }
@@ -996,10 +1024,11 @@
     }
     dc.config_files.push_back(fn);
     map<char*, int, ltstr> commands;
-    enum {dummy, tld, content, hostlimit, htmllimit, htmltag, dnsbl, dnsbll, envfrom, envto, include, includedcc};
+    enum {dummy, tld, content, hostlimit, hostrandom, htmllimit, htmltag, dnsbl, dnsbll, envfrom, envto, include, includedcc};
     commands["tld"        ] = tld;
     commands["content"    ] = content;
     commands["host_limit" ] = hostlimit;
+    commands["host_random"] = hostrandom;
     commands["html_limit" ] = htmllimit;
     commands["html_tag"   ] = htmltag;
     commands["dnsbl"      ] = dnsbl;
@@ -1065,6 +1094,11 @@
                     processed = true;
                     } break;
 
+                case hostrandom: {
+                    dc.host_random = true;
+                    processed = true;
+                    } break;
+
                 case htmllimit: {
                     char *limit = strtok(NULL, delim);
                     if (!limit) break;                          // no integer limit