summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/greylist.c113
1 files changed, 88 insertions, 25 deletions
diff --git a/tools/greylist.c b/tools/greylist.c
index d76ba08..b64636e 100644
--- a/tools/greylist.c
+++ b/tools/greylist.c
@@ -3,7 +3,7 @@
#include <iomanip>
#include <string>
-#include <sys/types.h> /* for stat() */
+#include <sys/types.h> /* for stat(), getaddrinfo() */
#include <sys/stat.h> /* for stat() */
#include <unistd.h> /* for stat() */
#include <stdio.h> /* for perror */
@@ -17,6 +17,10 @@
// requires apt-get install libboost-filesystem-dev:
#include <boost/filesystem.hpp>
+#include <sys/socket.h> /* for getaddrinfo() */
+#include <netdb.h> /* for getaddrinfo() */
+#include <string.h> /* for memset() */
+
using namespace std;
const int minute(60);
@@ -84,6 +88,8 @@ public:
string progname;
pid_t mypid;
timeval now;
+ char* ipvar;
+ char* hostvar;
string ipbase;
string ipname;
string hostname;
@@ -104,7 +110,8 @@ public:
// access comes after modification:
void update(const string msg, const timeval new_mod,
const timeval new_ac, const int penalty=0);
- void bind();
+ int setup();
+ int check_dns();
};
string basename(const string path){
@@ -113,11 +120,24 @@ string basename(const string path){
return path;
}
-void whatsit::bind(){
+int whatsit::setup(){
stringstream foo;
- foo << basename(progname) << suffix
+ foo << basename(progname) << suffix
<< "[" << mypid << "]";
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;
+ hostvar = getenv("TCPREMOTEHOST");
+ if (hostvar) hostname = hostvar;
+ return 0;
}
string time_out(const int _ttt){
@@ -218,6 +238,7 @@ void whatsit::update(const string msg, const timeval new_mod,
utimes(ipname.c_str(), upd);
}
+
int main(int _argc, char** _argv){
mypid = getpid();
int argc(_argc);
@@ -256,7 +277,7 @@ int main(int _argc, char** _argv){
exeunt(ex_syserr);
}
}
- foo.bind();
+ if (foo.setup()) return ex_syserr;
if (scanmode) {
scan(foo.progid, dirname, copies);
@@ -269,31 +290,15 @@ int main(int _argc, char** _argv){
// check mode ... perform some extra checks.
// Probably a better design would be to
-// a) make more thorough DNS checks, and
-// b) move all the DNS checking to a separate module
+// (a) make more thorough DNS checks, and
+// (b) move all the DNS checking to a separate module
- char* hostvar = getenv("TCPREMOTEHOST");
- if (!hostvar) {
- cerr << foo.progid
- << " from " << foo.ipbase
- << " ... TCPREMOTEHOST not set???" << endl;
- exeunt(ex_spam);
- }
+ int dns = foo.check_dns();
+ if (dns == ex_syserr) return dns;
exeunt(sts);
}
int whatsit::doit(const int penalty){
- char* 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;
- char* hostvar = getenv("TCPREMOTEHOST");
- if (hostvar) hostname = hostvar;
// see if our directory exists:
struct stat dirstat;
@@ -365,3 +370,61 @@ int whatsit::doit(const int penalty){
update("returning customer", mod_orig, now, penalty);
return 0;
}
+
+int whatsit::check_dns(){
+ char* hostvar = getenv("TCPREMOTEHOST");
+ if (!hostvar) {
+ cerr << progid
+ << " from " << ipbase
+ << " ... TCPREMOTEHOST not set???" << endl;
+ exeunt(ex_spam);
+ }
+
+ struct addrinfo *result;
+ struct addrinfo *ipresult;
+ struct addrinfo *res;
+ addrinfo hints;
+ int error;
+
+ /* 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
+ hints.ai_protocol = IPPROTO_TCP;
+#endif
+ error = getaddrinfo(hostvar, NULL, &hints, &result);
+ if (error) {
+ cerr << "error in getaddrinfo for " << hostvar
+ << " : " << gai_strerror(error) << endl;
+ return ex_syserr;
+ }
+
+ error = getaddrinfo(ipvar, NULL, &hints, &ipresult);
+ if (error) {
+ cerr << "error in getaddrinfo for " << ipvar
+ << " : " << gai_strerror(error) << endl;
+ return ex_syserr;
+ }
+
+// loop over all returned results and check for a match.
+ for (res = result; res != NULL; res = res->ai_next){
+ void *numericAddress;
+
+ sa_family_t fam = ((sockaddr *)res->ai_addr)->sa_family;
+ int addrsize;
+ switch (fam) {
+ case AF_INET:
+ numericAddress = &(((sockaddr_in *)res->ai_addr)->sin_addr.s_addr);
+ addrsize = sizeof(in_addr);
+ break;
+ case AF_INET6:
+ numericAddress = &(((sockaddr_in6 *)res->ai_addr)->sin6_addr.s6_addr);
+ addrsize = sizeof(in6_addr);
+ break;
+ default:
+ cerr << "?Unknown address family " << fam << endl;
+ return(ex_syserr);
+ }
+ }
+ return 0;
+}