http://blog.powerdns.com/2014/02/06/related-to-recent-dos-attacks-recursor-configuration-file-guidance/ https://github.com/Habbie/pdns/commit/e24b124a4c7b49f38ff8bcf6926cd69077d16ad8 diff -Naurp pdns-3.3.1/pdns/misc.cc pdns-3.3.1.oden/pdns/misc.cc --- pdns-3.3.1/pdns/misc.cc 2013-12-17 14:47:33.000000000 +0100 +++ pdns-3.3.1.oden/pdns/misc.cc 2014-06-12 13:02:29.847155292 +0200 @@ -1,6 +1,6 @@ /* PowerDNS Versatile Database Driven Nameserver - Copyright (C) 2002 - 2010 PowerDNS.COM BV + Copyright (C) 2002 - 2014 PowerDNS.COM BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 @@ -22,6 +22,7 @@ #include <netdb.h> #include <sys/time.h> #include <time.h> +#include <sys/resource.h> #include <netinet/in.h> #include <unistd.h> #endif // WIN32 @@ -784,3 +785,22 @@ Regex::Regex(const string &expr) if(regcomp(&d_preg, expr.c_str(), REG_ICASE|REG_NOSUB|REG_EXTENDED)) throw AhuException("Regular expression did not compile"); } + +unsigned int getFilenumLimit(bool hardOrSoft) +{ + struct rlimit rlim; + if(getrlimit(RLIMIT_NOFILE, &rlim) < 0) + unixDie("Requesting number of available file descriptors"); + return hardOrSoft ? rlim.rlim_max : rlim.rlim_cur; +} + +void setFilenumLimit(unsigned int lim) +{ + struct rlimit rlim; + + if(getrlimit(RLIMIT_NOFILE, &rlim) < 0) + unixDie("Requesting number of available file descriptors"); + rlim.rlim_cur=lim; + if(setrlimit(RLIMIT_NOFILE, &rlim) < 0) + unixDie("Setting number of available file descriptors"); +} diff -Naurp pdns-3.3.1/pdns/misc.hh pdns-3.3.1.oden/pdns/misc.hh --- pdns-3.3.1/pdns/misc.hh 2013-12-17 14:47:33.000000000 +0100 +++ pdns-3.3.1.oden/pdns/misc.hh 2014-06-12 13:02:33.184155478 +0200 @@ -507,4 +507,6 @@ private: regex_t d_preg; }; +unsigned int getFilenumLimit(bool hardOrSoft=0); +void setFilenumLimit(unsigned int lim); #endif diff -Naurp pdns-3.3.1/pdns/pdns_recursor.cc pdns-3.3.1.oden/pdns/pdns_recursor.cc --- pdns-3.3.1/pdns/pdns_recursor.cc 2013-12-17 14:47:33.000000000 +0100 +++ pdns-3.3.1.oden/pdns/pdns_recursor.cc 2014-06-12 13:02:39.467155829 +0200 @@ -1816,7 +1816,22 @@ int serviceMain(int argc, char*argv[]) g_tcpTimeout=::arg().asNum("client-tcp-timeout"); g_maxTCPPerClient=::arg().asNum("max-tcp-per-client"); - g_maxMThreads=::arg().asNum("max-mthreads"); + g_maxMThreads=::arg().asNum("max-mthreads"); + unsigned int availFDs=getFilenumLimit(); + if(g_maxMThreads * g_numThreads > availFDs) { + if(getFilenumLimit(true) >= g_maxMThreads * g_numThreads) { + setFilenumLimit(g_maxMThreads * g_numThreads); + L<<Logger::Warning<<"Raised soft limit on number of filedescriptors to "<<g_maxMThreads * g_numThreads<<" to match max-mthreads and threads settings"<<endl; + } + else { + int newval = getFilenumLimit(true) / g_numThreads; + L<<Logger::Warning<<"Insufficient number of filedescriptors available for max-mthreads*threads setting! ("<<availFDs<<" < "<<g_maxMThreads*g_numThreads<<"), reducing max-mthreads to "<<newval<<endl; + g_maxMThreads = newval; + setFilenumLimit(g_maxMThreads * g_numThreads); + } + + + } if(g_numThreads == 1) { L<<Logger::Warning<<"Operating unthreaded"<<endl;