diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/greylist.c | 113 | 
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; +}  | 
