7 #include "dnsrecords.hh"
8 #include "dnsparser.hh"
9 #include <boost/tuple/tuple.hpp>
10 #include <boost/tuple/tuple_comparison.hpp>
11 #include <boost/algorithm/string.hpp>
18 #include "namespaces.hh"
19 #include "namespaces.hh"
23 struct tm
* pdns_localtime_r(const uint32_t* then
, struct tm
* tm
)
27 return localtime_r(&t
, tm
);
30 int32_t g_clientQuestions
, g_clientResponses
, g_serverQuestions
, g_serverResponses
, g_skipped
;
31 struct pdns_timeval g_lastanswerTime
, g_lastquestionTime
;
32 void makeReport(const struct pdns_timeval
& tv
)
34 int64_t clientdiff
= g_clientQuestions
- g_clientResponses
;
35 int64_t serverdiff
= g_serverQuestions
- g_serverResponses
;
37 if(clientdiff
> 5 && clientdiff
> 0.02*g_clientQuestions
) {
39 struct tm tm
=*pdns_localtime_r(&tv
.tv_sec
, &tm
);
40 strftime(tmp
, sizeof(tmp
) - 1, "%F %H:%M:%S", &tm
);
42 cout
<< tmp
<< ": Resolver dropped too many questions ("
43 << g_clientQuestions
<<" vs " << g_clientResponses
<< "), diff: " <<clientdiff
<<endl
;
45 tm
=*pdns_localtime_r(&g_lastanswerTime
.tv_sec
, &tm
);
46 strftime(tmp
, sizeof(tmp
) - 1, "%F %H:%M:%S", &tm
);
48 cout
<<"Last answer: "<<tmp
<<"."<<g_lastanswerTime
.tv_usec
/1000000.0<<endl
;
50 tm
=*pdns_localtime_r(&g_lastquestionTime
.tv_sec
, &tm
);
51 strftime(tmp
, sizeof(tmp
) - 1, "%F %H:%M:%S", &tm
);
53 cout
<<"Last question: "<<tmp
<<"."<<g_lastquestionTime
.tv_usec
/1000000.0<<endl
;
56 if(serverdiff
> 5 && serverdiff
> 0.02*g_serverQuestions
) {
58 struct tm tm
=*pdns_localtime_r(&tv
.tv_sec
, &tm
);
59 strftime(tmp
, sizeof(tmp
) - 1, "%F %H:%M:%S", &tm
);
61 cout
<< tmp
<< ": Auth server dropped too many questions ("
62 << g_serverQuestions
<<" vs " << g_serverResponses
<< "), diff: " <<serverdiff
<<endl
;
64 tm
=*pdns_localtime_r(&g_lastanswerTime
.tv_sec
, &tm
);
65 strftime(tmp
, sizeof(tmp
) - 1, "%F %H:%M:%S", &tm
);
67 cout
<<"Last answer: "<<tmp
<<"."<<g_lastanswerTime
.tv_usec
/1000000.0<<endl
;
69 tm
=*pdns_localtime_r(&g_lastquestionTime
.tv_sec
, &tm
);
70 strftime(tmp
, sizeof(tmp
) - 1, "%F %H:%M:%S", &tm
);
72 cout
<<"Last question: "<<tmp
<<"."<<g_lastquestionTime
.tv_usec
/1000000.0<<endl
;
74 // cout <<"Recursive questions: "<<g_clientQuestions<<", recursive responses: " << g_clientResponses<<
75 // ", server questions: "<<g_serverQuestions<<", server responses: "<<g_serverResponses<<endl;
78 // cerr << tv.tv_sec << " " <<g_clientQuestions<<" " << g_clientResponses<< " "<<g_serverQuestions<<" "<<g_serverResponses<<" "<<g_skipped<<endl;
79 g_clientQuestions
=g_clientResponses
=g_serverQuestions
=g_serverResponses
=0;
84 int main(int argc
, char** argv
)
88 for(int n
=1 ; n
< argc
; ++n
) {
90 unsigned int parseErrors
=0, totalQueries
=0, skipped
=0;
91 PcapPacketReader
pr(argv
[n
]);
92 // PcapPacketWriter pw(argv[n]+string(".out"), pr);
93 /* four sorts of packets:
94 "rd": question from a client pc
95 "rd qr": answer to a client pc
96 "": question from the resolver
97 "qr": answer to the resolver */
99 /* what are interesting events to note? */
100 /* we measure every 60 seconds, each interval with 10% less answers than questions is interesting */
103 struct pdns_timeval lastreport
={0, 0};
105 typedef set
<pair
<string
, uint16_t> > queries_t
;
106 queries_t questions
, answers
;
108 // unsigned int count = 50000;
110 map
<pair
<string
, uint16_t>, int> counts
;
112 while(pr
.getUDPPacket()) {
113 if((ntohs(pr
.d_udp
->uh_dport
)==5300 || ntohs(pr
.d_udp
->uh_sport
)==5300 ||
114 ntohs(pr
.d_udp
->uh_dport
)==53 || ntohs(pr
.d_udp
->uh_sport
)==53) &&
117 MOADNSParser
mdp((const char*)pr
.d_payload
, pr
.d_len
);
119 if(lastreport
.tv_sec
== 0) {
120 lastreport
= pr
.d_pheader
.ts
;
123 if(mdp
.d_header
.rd
&& !mdp
.d_header
.qr
) {
124 g_lastquestionTime
=pr
.d_pheader
.ts
;
127 counts
[make_pair(mdp
.d_qname
, mdp
.d_qtype
)]++;
128 questions
.insert(make_pair(mdp
.d_qname
, mdp
.d_qtype
));
130 else if(mdp
.d_header
.rd
&& mdp
.d_header
.qr
) {
131 g_lastanswerTime
=pr
.d_pheader
.ts
;
133 answers
.insert(make_pair(mdp
.d_qname
, mdp
.d_qtype
));
135 else if(!mdp
.d_header
.rd
&& !mdp
.d_header
.qr
) {
136 g_lastquestionTime
=pr
.d_pheader
.ts
;
138 counts
[make_pair(mdp
.d_qname
, mdp
.d_qtype
)]++;
139 questions
.insert(make_pair(mdp
.d_qname
, mdp
.d_qtype
));
142 else if(!mdp
.d_header
.rd
&& mdp
.d_header
.qr
) {
143 answers
.insert(make_pair(mdp
.d_qname
, mdp
.d_qtype
));
147 if(pr
.d_pheader
.ts
.tv_sec
- lastreport
.tv_sec
>= 5) {
148 makeReport(pr
.d_pheader
.ts
);
149 lastreport
= pr
.d_pheader
.ts
;
152 catch(MOADNSException
& mde
) {
153 // cerr<<"error parsing packet: "<<mde.what()<<endl;
157 catch(std::exception
& e
) {
158 cerr
<< e
.what() << endl
;
164 cerr
<<"Parse errors: "<<parseErrors
<<", total queries: "<<totalQueries
<<endl
;
165 typedef vector
<queries_t::value_type
> diff_t
;
167 set_difference(questions
.begin(), questions
.end(), answers
.begin(), answers
.end(), back_inserter(diff
));
168 cerr
<<questions
.size()<<" different rd questions, "<< answers
.size()<<" different rd answers, diff: "<<diff
.size()<<endl
;
169 cerr
<<skipped
<<" skipped\n";
171 cerr
<<"Generating 'failed' file with failed queries and counts\n";
172 ofstream
failed("failed");
173 failed
<<"name\ttype\tnumber\n";
174 for(diff_t::const_iterator i
= diff
.begin(); i
!= diff
.end() ; ++i
) {
175 failed
<< i
->first
<< "\t" << DNSRecordContent::NumberToType(i
->second
) << "\t"<< counts
[make_pair(i
->first
, i
->second
)]<<"\n";
180 set_difference(answers
.begin(), answers
.end(), questions
.begin(), questions
.end(), back_inserter(diff
));
181 cerr
<<diff
.size()<<" answers w/o questions\n";
183 cerr
<<"Generating 'succeeded' file with all unique answers and counts\n";
184 ofstream
succeeded("succeeded");
185 succeeded
<<"name\ttype\tnumber\n";
186 for(queries_t::const_iterator i
= answers
.begin(); i
!= answers
.end() ; ++i
) {
187 succeeded
<< i
->first
<< "\t" <<DNSRecordContent::NumberToType(i
->second
) << "\t" << counts
[make_pair(i
->first
, i
->second
)]<<"\n";
191 catch(std::exception
& e
)
193 cerr
<<"Fatal: "<<e
.what()<<endl
;