]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsgram.cc
Include config.h only in .cc files
[thirdparty/pdns.git] / pdns / dnsgram.cc
1 #define __FAVOR_BSD
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5 #include "statbag.hh"
6 #include "dnspcap.hh"
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>
12 #include <map>
13 #include <set>
14 #include <fstream>
15 #include <algorithm>
16 #include "anadns.hh"
17
18 #include "namespaces.hh"
19 #include "namespaces.hh"
20
21 StatBag S;
22
23 struct tm* pdns_localtime_r(const uint32_t* then, struct tm* tm)
24 {
25 time_t t = *then;
26
27 return localtime_r(&t, tm);
28 }
29
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)
33 {
34 int64_t clientdiff = g_clientQuestions - g_clientResponses;
35 int64_t serverdiff = g_serverQuestions - g_serverResponses;
36
37 if(clientdiff > 5 && clientdiff > 0.02*g_clientQuestions) {
38 char tmp[80];
39 struct tm tm=*pdns_localtime_r(&tv.tv_sec, &tm);
40 strftime(tmp, sizeof(tmp) - 1, "%F %H:%M:%S", &tm);
41
42 cout << tmp << ": Resolver dropped too many questions ("
43 << g_clientQuestions <<" vs " << g_clientResponses << "), diff: " <<clientdiff<<endl;
44
45 tm=*pdns_localtime_r(&g_lastanswerTime.tv_sec, &tm);
46 strftime(tmp, sizeof(tmp) - 1, "%F %H:%M:%S", &tm);
47
48 cout<<"Last answer: "<<tmp<<"."<<g_lastanswerTime.tv_usec/1000000.0<<endl;
49
50 tm=*pdns_localtime_r(&g_lastquestionTime.tv_sec, &tm);
51 strftime(tmp, sizeof(tmp) - 1, "%F %H:%M:%S", &tm);
52
53 cout<<"Last question: "<<tmp<<"."<<g_lastquestionTime.tv_usec/1000000.0<<endl;
54 }
55
56 if(serverdiff > 5 && serverdiff > 0.02*g_serverQuestions) {
57 char tmp[80];
58 struct tm tm=*pdns_localtime_r(&tv.tv_sec, &tm);
59 strftime(tmp, sizeof(tmp) - 1, "%F %H:%M:%S", &tm);
60
61 cout << tmp << ": Auth server dropped too many questions ("
62 << g_serverQuestions <<" vs " << g_serverResponses << "), diff: " <<serverdiff<<endl;
63
64 tm=*pdns_localtime_r(&g_lastanswerTime.tv_sec, &tm);
65 strftime(tmp, sizeof(tmp) - 1, "%F %H:%M:%S", &tm);
66
67 cout<<"Last answer: "<<tmp<<"."<<g_lastanswerTime.tv_usec/1000000.0<<endl;
68
69 tm=*pdns_localtime_r(&g_lastquestionTime.tv_sec, &tm);
70 strftime(tmp, sizeof(tmp) - 1, "%F %H:%M:%S", &tm);
71
72 cout<<"Last question: "<<tmp<<"."<<g_lastquestionTime.tv_usec/1000000.0<<endl;
73 }
74 // cout <<"Recursive questions: "<<g_clientQuestions<<", recursive responses: " << g_clientResponses<<
75 // ", server questions: "<<g_serverQuestions<<", server responses: "<<g_serverResponses<<endl;
76
77
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;
80 g_skipped=0;
81 }
82
83
84 int main(int argc, char** argv)
85 try
86 {
87 reportAllTypes();
88 for(int n=1 ; n < argc; ++n) {
89 cout<<argv[n]<<endl;
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 */
98
99 /* what are interesting events to note? */
100 /* we measure every 60 seconds, each interval with 10% less answers than questions is interesting */
101 /* report chunked */
102
103 struct pdns_timeval lastreport={0, 0};
104
105 typedef set<pair<string, uint16_t> > queries_t;
106 queries_t questions, answers;
107
108 // unsigned int count = 50000;
109
110 map<pair<string, uint16_t>, int> counts;
111
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) &&
115 pr.d_len > 12) {
116 try {
117 MOADNSParser mdp((const char*)pr.d_payload, pr.d_len);
118
119 if(lastreport.tv_sec == 0) {
120 lastreport = pr.d_pheader.ts;
121 }
122
123 if(mdp.d_header.rd && !mdp.d_header.qr) {
124 g_lastquestionTime=pr.d_pheader.ts;
125 g_clientQuestions++;
126 totalQueries++;
127 counts[make_pair(mdp.d_qname, mdp.d_qtype)]++;
128 questions.insert(make_pair(mdp.d_qname, mdp.d_qtype));
129 }
130 else if(mdp.d_header.rd && mdp.d_header.qr) {
131 g_lastanswerTime=pr.d_pheader.ts;
132 g_clientResponses++;
133 answers.insert(make_pair(mdp.d_qname, mdp.d_qtype));
134 }
135 else if(!mdp.d_header.rd && !mdp.d_header.qr) {
136 g_lastquestionTime=pr.d_pheader.ts;
137 g_serverQuestions++;
138 counts[make_pair(mdp.d_qname, mdp.d_qtype)]++;
139 questions.insert(make_pair(mdp.d_qname, mdp.d_qtype));
140 totalQueries++;
141 }
142 else if(!mdp.d_header.rd && mdp.d_header.qr) {
143 answers.insert(make_pair(mdp.d_qname, mdp.d_qtype));
144 g_serverResponses++;
145 }
146
147 if(pr.d_pheader.ts.tv_sec - lastreport.tv_sec >= 5) {
148 makeReport(pr.d_pheader.ts);
149 lastreport = pr.d_pheader.ts;
150 }
151 }
152 catch(MOADNSException& mde) {
153 // cerr<<"error parsing packet: "<<mde.what()<<endl;
154 parseErrors++;
155 continue;
156 }
157 catch(std::exception& e) {
158 cerr << e.what() << endl;
159 continue;
160 }
161 }
162
163 }
164 cerr<<"Parse errors: "<<parseErrors<<", total queries: "<<totalQueries<<endl;
165 typedef vector<queries_t::value_type> diff_t;
166 diff_t diff;
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";
170
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";
176 }
177
178 diff.clear();
179
180 set_difference(answers.begin(), answers.end(), questions.begin(), questions.end(), back_inserter(diff));
181 cerr<<diff.size()<<" answers w/o questions\n";
182
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";
188 }
189 }
190 }
191 catch(std::exception& e)
192 {
193 cerr<<"Fatal: "<<e.what()<<endl;
194 }