root/trunk/pdns/pdns/dnsbulktest.cc @ 1634

Revision 1634, 5.0 KB (checked in by ahu, 3 years ago)

add timeout reporting to inflighter

Line 
1#include "inflighter.cc"
2#include <deque>
3#include "namespaces.hh"
4#include "dnsparser.hh"
5#include "sstuff.hh"
6#include "misc.hh"
7#include "dnswriter.hh"
8#include "dnsrecords.hh"
9
10StatBag S;
11
12struct DNSResult
13{
14  vector<ComboAddress> ips;
15  int rcode;
16  bool seenauthsoa;
17};
18
19struct SendReceive
20{
21  typedef int Identifier;
22  typedef DNSResult Answer; // ip
23  int d_socket;
24  deque<uint16_t> d_idqueue;
25 
26 
27  SendReceive(const std::string& remoteAddr, uint16_t port)
28  {
29    d_socket = socket(AF_INET, SOCK_DGRAM, 0);
30    int val=1;
31    setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
32   
33    ComboAddress remote(remoteAddr, port);
34    connect(d_socket, (struct sockaddr*)&remote, remote.getSocklen());
35    d_oks = d_errors = d_nodatas = d_nxdomains = d_unknowns = 0;
36    d_receiveds = d_receiveerrors = 0;
37    for(unsigned int id =0 ; id < numeric_limits<uint16_t>::max(); ++id) 
38      d_idqueue.push_back(id);
39  }
40 
41  ~SendReceive()
42  {
43    close(d_socket);
44  }
45 
46  Identifier send(string& domain)
47  {
48    //cerr<<"Sending query for '"<<domain<<"'"<<endl;
49   
50    // send it, copy code from 'sdig'
51    vector<uint8_t> packet;
52 
53    DNSPacketWriter pw(packet, domain, QType::A);
54   
55    pw.getHeader()->id = d_idqueue.front();
56    d_idqueue.pop_front();
57    pw.getHeader()->rd = 1;
58    pw.getHeader()->qr = 0;
59   
60    ::send(d_socket, &*packet.begin(), packet.size(), 0);
61   
62    return pw.getHeader()->id;
63  }
64 
65  bool receive(Identifier& id, DNSResult& dr)
66  {
67    if(waitForData(d_socket, 0, 500000) > 0) {
68      char buf[512];
69         
70      int len = recv(d_socket, buf, sizeof(buf), 0);
71      if(len < 0) {
72        d_receiveerrors++;
73        return 0;
74      }
75      else {
76        d_receiveds++;
77      }
78      // parse packet, set 'id', fill out 'ip'
79     
80      MOADNSParser mdp(string(buf, len));
81      cout<<"Reply to question for qname='"<<mdp.d_qname<<"', qtype="<<DNSRecordContent::NumberToType(mdp.d_qtype)<<endl;
82      cout<<"Rcode: "<<mdp.d_header.rcode<<", RD: "<<mdp.d_header.rd<<", QR: "<<mdp.d_header.qr;
83      cout<<", TC: "<<mdp.d_header.tc<<", AA: "<<mdp.d_header.aa<<", opcode: "<<mdp.d_header.opcode<<endl;
84      dr.rcode = mdp.d_header.rcode;
85      for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {         
86        if(i->first.d_place == 1 && i->first.d_type == QType::A)
87          dr.ips.push_back(ComboAddress(i->first.d_content->getZoneRepresentation()));
88        if(i->first.d_place == 2 && i->first.d_type == QType::SOA) {
89          dr.seenauthsoa = 1;
90        }
91        cout<<i->first.d_place-1<<"\t"<<i->first.d_label<<"\tIN\t"<<DNSRecordContent::NumberToType(i->first.d_type);
92        cout<<"\t"<<i->first.d_ttl<<"\t"<< i->first.d_content->getZoneRepresentation()<<"\n";
93      }
94     
95      id = mdp.d_header.id;
96   
97      return 1;
98    }
99    return 0;
100  }
101 
102  void deliverTimeout(const Identifier& id)
103  {
104    d_idqueue.push_back(id);
105  }
106 
107  void deliverAnswer(string& domain, const DNSResult& dr)
108  {
109    cout<<domain<<": rcode: "<<dr.rcode;
110    BOOST_FOREACH(const ComboAddress& ca, dr.ips) {
111      cout<<", "<<ca.toString();
112    }
113    cout<<endl;
114    if(dr.rcode == RCode::NXDomain) {
115      d_nxdomains++;
116    }
117    else if(dr.rcode) {
118      d_errors++;
119    }
120    else if(dr.ips.empty() && dr.seenauthsoa) 
121      d_nodatas++;
122    else if(!dr.ips.empty())
123      d_oks++;
124    else {
125      cout<<"UNKNOWN!! ^^"<<endl;
126      d_unknowns++;
127    }
128  }
129  unsigned int d_errors, d_nxdomains, d_nodatas, d_oks, d_unknowns;
130  unsigned int d_receiveds, d_receiveerrors;
131};
132
133
134int main(int argc, char** argv)
135{
136  SendReceive sr(argv[1], atoi(argv[2]));
137  unsigned int limit = 0;
138  if(argc==4)
139    limit = atoi(argv[3]);
140   
141  reportAllTypes();
142  vector<string> domains;
143   
144  Inflighter<vector<string>, SendReceive> inflighter(domains, sr);
145  inflighter.d_maxInFlight = 1000;
146  inflighter.d_timeoutSeconds = 15;
147  string line;
148 
149  pair<string, string> split;
150  while(stringfgets(stdin, line)) {
151    if(limit && domains.size() >= limit)
152      break;
153     
154    trim_right(line);
155    split=splitField(line,',');
156    domains.push_back(split.second);
157    domains.push_back("www."+split.second);
158  }
159  cerr<<"Read "<<domains.size()<<" domains!"<<endl;
160  random_shuffle(domains.begin(), domains.end());
161
162  for(;;) {
163    try {
164      inflighter.run();
165      break;
166    }
167    catch(exception& e) {
168      cerr<<"Caught exception: "<<e.what()<<endl;
169    }
170  }
171  cerr<<"Results: "<<sr.d_errors<<" errors, "<<sr.d_oks<<" oks, "<<sr.d_nodatas<<" nodatas, "<<sr.d_nxdomains<<" nxdomains, "<<inflighter.getTimeouts()<<" timeouts"<<endl;
172  cerr<<sr.d_unknowns<<" answers with an unknown status"<<endl;
173 
174  cerr<<domains.size() - (sr.d_errors + sr.d_oks + sr.d_nodatas + sr.d_nxdomains + inflighter.getTimeouts() + sr.d_unknowns)<<" status results missing"<<endl;
175  cerr<<sr.d_receiveerrors<<" receive errors, "<<sr.d_receiveds<<" packets received correctly"<<endl;
176
177  cerr<<inflighter.getUnexpecteds()<<" unexpected responses (probably seen as timeouts)"<<endl;
178}
179
180
Note: See TracBrowser for help on using the browser.