summaryrefslogtreecommitdiff
path: root/tools/greylist.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/greylist.c')
-rw-r--r--tools/greylist.c93
1 files changed, 56 insertions, 37 deletions
diff --git a/tools/greylist.c b/tools/greylist.c
index 063c3d0..fd5ac4f 100644
--- a/tools/greylist.c
+++ b/tools/greylist.c
@@ -38,6 +38,7 @@ const int probation(4*hour);
#define bar foo(good, 0) ;\
foo(spam, 21) ;\
foo(penaltybox, 22) ;\
+foo(badDNS, 23) ;\
foo(greylisting, 70) ;\
foo(syserr, 71) ;\
foo(comerr, 74) ;
@@ -118,6 +119,7 @@ public:
const timeval new_ac, const int penalty=0);
int setup();
int check_dns();
+ int check_dns_sub(string &addr, string &host, vector<string> &checked);
};
string basename(const string path){
@@ -133,14 +135,7 @@ int whatsit::setup(){
progid = foo.str();
ipvar = getenv("TCPREMOTEIP");
- if (!ipvar) {
- cerr << progid
- << " TCPREMOTEIP not set???" << endl;
- // should never happen
- // although you can make it happen using a weird test-harness
- return(ex_syserr);
- }
- ipbase = ipvar;
+ if (ipvar) ipbase = ipvar;
hostvar = getenv("TCPREMOTEHOST");
if (hostvar) hostname = hostvar;
return 0;
@@ -306,6 +301,14 @@ int main(int _argc, char** _argv){
int whatsit::doit(const int penalty){
+ if (!ipvar) {
+ cerr << progid
+ << " TCPREMOTEIP not set???" << endl;
+ // should never happen
+ // although you can make it happen using a weird test-harness
+ return(ex_syserr);
+ }
+
// see if our directory exists:
struct stat dirstat;
int rslt = stat(dirname.c_str(), &dirstat);
@@ -356,6 +359,7 @@ int whatsit::doit(const int penalty){
return(ex_penaltybox);
}
if (mod_age < ac_age){
+// when he comes out on parole, he starts over with no reputation:
update("paroled spammer", now, now, penalty);
return(ex_greylisting);
}
@@ -427,23 +431,35 @@ int diff(const VU aaa, const VU bbb){
}
int whatsit::check_dns(){
- char* hostvar = getenv("TCPREMOTEHOST");
- if (!hostvar) {
- cerr << progid
- << " from " << ipbase
- << " ... TCPREMOTEHOST not set???" << endl;
- exeunt(ex_spam);
- }
+ string addr("()"), host("()");
+ vector<string> checked;
+ int sts = check_dns_sub(addr, host, checked);
+ if (sts == 0) return sts;
+ if (sts != ex_badDNS) return sts; // possible ex_syserr
+#if 1
+ sts = 0; // demote badDNS to just a warning
+#endif
+ cerr << progid;
+ if (!sts) cerr << " (warning)";
+ cerr << " DNS inconsistency: "
+ << addr << " --> "
+ << host << " ==>";
+ if (!checked.size()) cerr << " ()";
+ else for (vector<string>::const_iterator chk = checked.begin();
+ chk != checked.end(); chk++) cerr << " " << *chk;
+ cerr << endl;
+
+ return sts;
+}
+
+int whatsit::check_dns_sub(string &addr, string &host, vector<string> &checked){
struct addrinfo *result;
struct addrinfo *ipresult;
struct addrinfo *res;
addrinfo hints;
int error;
- int ex_dnserr(ex_syserr);
- ex_dnserr = 0; // temporarily just a warning
- /* resolve the domain name into a list of addresses */
memset(&hints, 0, sizeof(struct addrinfo));
#if 1
// restrict to TCP only; otherwise we get N records per address
@@ -451,43 +467,46 @@ int whatsit::check_dns(){
#endif
error = getaddrinfo(ipvar, NULL, &hints, &ipresult);
- if (error) {
- cerr << "error in getaddrinfo for " << ipvar
+ if (error == EAI_NONAME) return ex_badDNS;
+ if (error) { // some unexpected error
+ cerr << progid
+ << " odd error " << error
+ << " in getaddrinfo for " << ipvar
<< " : " << gai_strerror(error) << endl;
- return ex_dnserr;
+ return ex_syserr;
}
if (!ipresult) {
cerr << "should never happen (addr with no addrs?)" << endl;
- return ex_dnserr;
+ return ex_syserr;
}
-
VUx ipAddr = parse_sockaddr(ipresult->ai_addr);
+ addr = ipAddr.str();
+
+ char* hostvar = getenv("TCPREMOTEHOST");
+ if (hostvar) host = hostvar;
+ else return(ex_badDNS);
+
error = getaddrinfo(hostvar, NULL, &hints, &result);
+ if (error == EAI_NONAME) return ex_badDNS;
if (error) {
- cerr << "error in getaddrinfo for " << hostvar
- << " : " << gai_strerror(error) << endl;
- return ex_dnserr;
+ cerr << progid
+ << " error " << error
+ << " compare " << EAI_NONAME
+ << " in getaddrinfo for " << ipvar
+ << " :: " << gai_strerror(error) << endl;
+ return ex_syserr;
}
// loop over all returned results and check for a match.
- vector<string> checked_hosts;
for (res = result; res != NULL; res = res->ai_next){
VUx hostAddr = parse_sockaddr(res->ai_addr);
-
+ checked.push_back(hostAddr.str());
if (!diff(hostAddr.addr, ipAddr.addr)) {
///// cerr << "match! " << ipAddr.addr.size() << endl;
goto done;
}
}
- if (!ex_dnserr) cerr << "(warning) ";
- cerr << "DNS inconsistency: "
- << ipAddr.str() << " --> "
- << hostvar << " ==>";
- for (res = result; res != NULL; res = res->ai_next){
- cerr << " " << parse_sockaddr(res->ai_addr).str();
- }
- cerr << endl;
- return ex_dnserr;
+ return ex_badDNS;
done:
return 0;