]> granicus.if.org Git - pdns/commitdiff
lots
authorBert Hubert <bert.hubert@netherlabs.nl>
Thu, 22 Jan 2004 07:52:32 +0000 (07:52 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Thu, 22 Jan 2004 07:52:32 +0000 (07:52 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@222 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/Makefile.am
pdns/backends/bind/zone2sql.cc
pdns/misc.cc
pdns/misc.hh
pdns/qgen.cc [new file with mode: 0644]
pdns/syncres.hh

index 4f1e5aaadf59b298664c3ded6eae01b8b97a71a7..8e31fbd624b44627bde946b751fb9e923cf1dc5b 100644 (file)
@@ -16,7 +16,7 @@ else
 sbin_PROGRAMS = pdns_server
 endif
 
-bin_PROGRAMS = pdns_control
+bin_PROGRAMS = pdns_control qgen
 
 EXTRA_PROGRAMS=pdns_recursor pdns_control
 
@@ -42,8 +42,11 @@ pdns_server_LDFLAGS= @moduleobjects@ @modulelibs@ @DYNLINKFLAGS@ @LIBDL@ @THREAD
 pdns_server_INCLUDES=
 
 
-#resolver_SOURCES=resolver.cc resolver.hh misc.cc unix_utility.cc qtype.cc \
-#logger.cc statbag.cc dnspacket.cc arguments.cc  tres.cc
+qgen_SOURCES=resolver.cc resolver.hh misc.cc unix_utility.cc qtype.cc \
+       logger.cc statbag.cc dnspacket.cc arguments.cc  qgen.cc \
+        sillyrecords.cc
+
+qgen_LDFLAGS= @THREADFLAGS@ @DYNLINKFLAGS@ 
 
 # INCLUDES=-I/usr/include/mysql
 
index 0318ae7c1811c3b6ea4169e8f5699c248e5f9f9a..feaf13d174bd954d42a6e99e8c07ad33d811f898 100644 (file)
 */
 /* accepts a named.conf as parameter and outputs heaps of sql */
 
-// $Id: zone2sql.cc,v 1.8 2004/01/17 13:18:22 ahu Exp $ 
+// $Id: zone2sql.cc,v 1.9 2004/01/22 07:52:32 ahu Exp $ 
 #ifdef WIN32
 # pragma warning ( disable: 4786 )
-# include <unistd.h>
-#endif // WIN32
 
+#endif // WIN32
+#include <unistd.h>
 #include <string>
 #include <map>
 
index 8531bc26643a0d035cba6b0dd4b1394c91fb30f2..658ae9cfa52af0dae38c7086edfe835da7692295 100644 (file)
@@ -164,10 +164,7 @@ int waitForData(int fd, int seconds)
 
   ret = select( fd + 1, &readfds, NULL, NULL, &tv );
   if ( ret == -1 )
-  {
-    ret = -1;
     errno = ETIMEDOUT;
-  }
 
   return ret;
 }
index 6cb3883d40f0aa5043017e53d1ed0aba8fbf60ed..60d927879b231fcf8d050b8319a3067d150050da 100644 (file)
@@ -171,6 +171,14 @@ inline string toUpper( const string& s )
        return r;
 }
 
+inline double getTime()
+{
+  struct timeval now;
+  Utility::gettimeofday(&now,0);
+  
+  return now.tv_sec+now.tv_usec/1000000.0;
+}
+
 
 inline void chomp( string& line, const string& delim )
 {
diff --git a/pdns/qgen.cc b/pdns/qgen.cc
new file mode 100644 (file)
index 0000000..004d99f
--- /dev/null
@@ -0,0 +1,287 @@
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <set>
+#include <utility>
+#include "dnspacket.hh"
+#include "qtype.hh"
+#include "dns.hh"
+#include "logger.hh"
+#include "statbag.hh"
+#include "arguments.hh"
+#include "ws.hh"
+using namespace std;
+Logger L;
+StatBag S;
+
+ArgvMap &arg()
+{
+  static ArgvMap theArg;
+  return theArg;
+}
+
+class QGen
+{
+  struct OutstandingQuestion
+  {
+    string qname;
+    QType qtype;
+    u_int16_t id;
+    double timeSent;
+    bool operator< (const OutstandingQuestion &rhs) const
+    {
+      if(qname < rhs.qname)
+       return true;
+      if(qname > rhs.qname)
+       return false;
+      return id < rhs.id;
+    }
+    bool operator==(const OutstandingQuestion &rhs) const
+    {
+      return qname==rhs.qname && id==rhs.id && qtype==rhs.qtype;
+    }
+  };
+
+  multiset<OutstandingQuestion> d_questions;
+  multiset<OutstandingQuestion> d_unanswered;
+
+  vector<string> d_new;
+
+  struct sockaddr_in d_toaddr;
+  ifstream d_in;
+
+  unsigned int d_port;
+  unsigned int d_numqueries;
+  unsigned int d_maxOutstanding;
+  unsigned int d_maxToRead;
+  unsigned int d_answeredOK;
+  unsigned int d_delayed;
+  unsigned int d_unmatched;
+  time_t d_laststats;
+  int d_clientsock;
+  string d_server;
+  Ewma d_ewma;
+
+  void unixDie(const string &why);
+  int fillAndSendQuestions();
+  void processAnswers();
+  void pruneUnanswered();
+  void sendQuestion(const string& qname, QType qtype);
+  static bool tooOld(const OutstandingQuestion &oq);
+  void printStats(bool force=false);
+
+public:
+  QGen(const string &server, unsigned int port, const string &fileName,
+       unsigned int maxOutstanding, unsigned int maxToRead);
+  void start();
+
+};
+
+void QGen::unixDie(const string &why)
+{
+  cerr<<"Fatal error, "<<why<<": "<<strerror(errno)<<endl;
+  exit(1);
+}
+
+
+QGen::QGen(const string &server,
+          unsigned int port,
+          const string &fileName,
+          unsigned int maxOutstanding,
+          unsigned int maxToRead) : d_in(fileName.c_str())
+{
+  d_answeredOK = d_numqueries = d_delayed = d_unmatched =0;
+
+  if(!d_in)
+    unixDie("unable to open '"+fileName+"'");
+
+  d_maxOutstanding = maxOutstanding;
+  d_maxToRead = maxToRead;
+
+  struct in_addr inp;
+  Utility::inet_aton(server.c_str(),&inp);
+  d_toaddr.sin_addr.s_addr=inp.s_addr;
+
+  d_toaddr.sin_port=htons(port);
+  d_toaddr.sin_family=AF_INET;
+
+  d_clientsock=socket(AF_INET, SOCK_DGRAM,0);
+  if(d_clientsock<0) 
+    throw AhuException("Making a socket for resolver: "+stringerror());
+  
+  struct sockaddr_in sin;
+  memset((char *)&sin,0, sizeof(sin));
+  
+  sin.sin_family = AF_INET;
+  sin.sin_addr.s_addr = INADDR_ANY;
+  sin.sin_port=0;
+
+  if (bind(d_clientsock, (struct sockaddr *)&sin, sizeof(sin))<0) 
+    unixDie("binding to socket");
+
+}
+
+void QGen::pruneUnanswered()
+{
+  double now=getTime();
+
+  for(multiset<OutstandingQuestion>::iterator i=d_questions.begin();i!=d_questions.end();) 
+    if(now-i->timeSent > 5) {
+      cout<<"No answer received to question for "<<i->qname<<endl;
+      d_unanswered.insert(*i);
+      d_questions.erase(i++);
+
+    }
+    else
+      ++i;
+
+}
+
+int QGen::fillAndSendQuestions()
+{
+  unsigned int wantToRead=d_maxOutstanding-d_questions.size();
+  string line;
+  int burst=50;
+
+  while(!d_in.eof() && wantToRead-- && burst--) {
+    getline(d_in,line);
+    chomp(line,"\r\n\t ");
+    vector<string> words;
+    stringtok(words,line," \t\n");
+
+    if(!line.empty()) {
+      int a,b,c,d;
+      if(line.find_first_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")==string::npos && 
+        sscanf(line.c_str(),"%d.%d.%d.%d",&a,&b,&c,&d)==4) {
+       ostringstream ostr;
+       ostr<<d<<"."<<c<<"."<<b<<"."<<a<<".in-addr.arpa";
+       sendQuestion(ostr.str(),QType(QType::PTR));
+
+      }
+      else
+       sendQuestion(words[0],(words.size() > 1) ? QType(QType::chartocode(words[1].c_str())) : QType(QType::A));
+    }
+  }
+  return d_questions.size();
+}
+
+void QGen::sendQuestion(const string& qname, QType qtype)
+{
+  DNSPacket p;
+  p.setQuestion(Opcode::Query,qname,qtype.getCode());
+  // set p.d.id here?
+  p.setRD(true);
+  p.wrapup();
+
+  if(sendto(d_clientsock, p.getData(), p.len, 0, (struct sockaddr*)(&d_toaddr), sizeof(d_toaddr))<0) 
+    unixDie("error sending packet");
+
+  OutstandingQuestion oq;
+  oq.id=p.d.id;
+  oq.qname=qname;
+  oq.qtype=qtype;
+  oq.timeSent=getTime();
+  
+  d_questions.insert(oq);
+  d_numqueries++;
+  //  cout<<"Sent packet with question "<<qname<<" and id "<<p.d.id<<": "<<d_questions.size()<<endl;
+}
+
+void QGen::printStats(bool force)
+{
+  if(!force && time(0)==d_laststats )
+    return;
+  d_laststats=time(0);
+  cout<<"Sent "<<d_numqueries<<" questions, "<<d_answeredOK<<" OK answers, ";
+  cout<<d_unanswered.size()<<" unanswered, "<<d_delayed<<" delayed, "<<d_unmatched<<" unmatched, "<<d_ewma.get1()<<"/s"<<endl;
+  d_ewma.submit(d_answeredOK);
+
+}
+
+void QGen::start()
+{
+  while(fillAndSendQuestions()) {
+    printStats();
+    processAnswers();
+    pruneUnanswered();
+  }
+
+  time_t end=time(0)+60;
+  while(time(0)<end && !d_unanswered.empty()) {
+    processAnswers();
+    printStats();
+  }
+  printStats(1);
+}
+
+void QGen::processAnswers()
+{
+  unsigned char buf[1500];
+  struct sockaddr_in fromaddr;
+  socklen_t addrlen=sizeof(fromaddr);
+  unsigned int len;
+  bool first(true);
+
+  while(waitForData(d_clientsock, first ? 1 : 0) > 0) {
+    first=false;
+    len=recvfrom(d_clientsock, reinterpret_cast<char *>(buf), sizeof(buf)-1,0,(struct sockaddr*)(&fromaddr), &addrlen);
+    DNSPacket p;
+    vector<DNSResourceRecord> answers;
+    try {
+      if(p.parse((char *)buf, len)<0) {
+       cerr<<"resolver: unable to parse packet of "+itoa(len)+" bytes"<<endl;
+       continue;
+      }
+      
+      answers= p.getAnswers();
+    }
+    catch(...) {
+      cerr<<"Got an error parsing packet"<<endl;
+      continue;
+    }
+
+    /*
+    cout<<"Packet: "<<p.d.id<<", "<<p.qdomain<<", rcode="<<p.d.rcode<<", ";
+    if(answers.empty())
+      cout<<"NO ANSWER"<<endl;
+    else cout<<answers[0].content<<endl;
+    */
+
+    OutstandingQuestion oq;
+    oq.qname=p.qdomain;
+    oq.id=p.d.id;
+    oq.qtype=p.qtype;
+    multiset<OutstandingQuestion>::const_iterator i=d_questions.find(oq);
+    if(i==d_questions.end()) {
+      if(d_unanswered.count(oq)) {
+       d_delayed++;
+       d_answeredOK++;
+       cout<<"Delayed answer for "<<p.qdomain<<" came in anyhow"<<endl;
+       d_unanswered.erase(oq);
+      }
+      else {
+       d_unmatched++;
+       cout<<"Unmatched answer, question: "<<p.qdomain<<endl;
+      }
+    }
+    else {
+      d_answeredOK++;
+      d_questions.erase(i);
+    }
+
+  }
+}
+
+int main(int argc, char **argv)
+{
+  string fileName="./questions";
+  string server="127.0.0.1";
+  unsigned int port=53;
+  unsigned int maxOutstanding=500;
+  unsigned int maxToRead=1000000;
+
+  // parse commandline here
+
+  QGen qg(server, port, fileName, maxOutstanding, maxToRead);
+  qg.start();
+}
index 7301680086d19b10cd0283b4371404ad8ad755b6..372f7269c6e7b39dc0489179ccd066ee2ff2f801 100644 (file)
@@ -90,13 +90,7 @@ public:
   }
 
 private:
-  double getTime()
-  {
-    struct timeval now;
-    Utility::gettimeofday(&now,0);
-    
-    return now.tv_sec+now.tv_usec/1000000.0;
-  }
+
   double d_last;
   double d_lastget;
   double d_val;