]>
Commit | Line | Data |
---|---|---|
12471842 PL |
1 | /* |
2 | * This file is part of PowerDNS or dnsdist. | |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * In addition, for the avoidance of any doubt, permission is granted to | |
10 | * link this program with OpenSSL and to (re)distribute the binaries | |
11 | * produced as the result of such linking. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
21 | */ | |
ca12836d | 22 | #include "statbag.hh" |
23 | #include "zoneparser-tng.hh" | |
24 | #include "namespaces.hh" | |
25 | #include "dnsrecords.hh" | |
26 | #include <fstream> | |
27 | #include <atomic> | |
28 | #include <thread> | |
29 | #include <unordered_set> | |
4e998d96 | 30 | #include <deque> |
ca12836d | 31 | #include "inflighter.cc" |
32 | //#include "malloctrace.hh" | |
33 | StatBag S; | |
34 | bool g_quiet; | |
35 | std::unique_ptr<ofstream> g_powerdns; | |
36 | std::atomic<unsigned int> g_count; | |
37 | std::atomic<bool> g_stop; | |
38 | ||
39 | ||
40 | struct namecount { | |
41 | set<DNSName> names; | |
42 | unsigned int count; | |
43 | bool isPowerDNS{false}; | |
44 | }; | |
45 | ||
46 | struct DNSResult | |
47 | { | |
48 | string content; | |
49 | int ttl{0}; | |
50 | uint16_t qclass; | |
51 | }; | |
52 | ||
53 | struct NSQuery | |
54 | { | |
55 | ComboAddress a; | |
56 | set<DNSName> nsnames; | |
57 | DNSName qname; | |
58 | unsigned int count; | |
59 | }; | |
60 | ||
61 | struct SendReceive | |
62 | { | |
63 | typedef int Identifier; | |
64 | typedef DNSResult Answer; // ip | |
65 | int d_socket; | |
4e998d96 | 66 | std::deque<uint16_t> d_idqueue; |
ca12836d | 67 | |
68 | SendReceive(map<ComboAddress, namecount, ComboAddress::addressOnlyLessThan>& res) : d_res(res) | |
69 | { | |
70 | d_socket = socket(AF_INET, SOCK_DGRAM, 0); | |
1ce8f718 AT |
71 | if (d_socket < 0) |
72 | throw runtime_error("socket(AF_INET, SOCK_DGRAM, 0) failed: " + stringerror()); | |
ca12836d | 73 | int val=1; |
ca12836d | 74 | |
1ce8f718 AT |
75 | if (setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) != 0) |
76 | cerr<<"Failed to turn on SO_REUSEADDR: " << stringerror() << endl; | |
77 | ||
ca12836d | 78 | for(unsigned int id =0 ; id < std::numeric_limits<uint16_t>::max(); ++id) |
79 | d_idqueue.push_back(id); | |
80 | } | |
81 | ||
82 | ~SendReceive() | |
83 | { | |
84 | close(d_socket); | |
85 | } | |
86 | ||
87 | Identifier send(NSQuery& domain) | |
88 | { | |
89 | //cerr<<"Sending query for '"<<domain<<"'"<<endl; | |
90 | ||
91 | // send it, copy code from 'sdig' | |
92 | vector<uint8_t> packet; | |
93 | ||
94 | DNSPacketWriter pw(packet, domain.qname, QType::TXT, 3); | |
95 | ||
96 | if(d_idqueue.empty()) { | |
97 | cerr<<"Exhausted ids!"<<endl; | |
98 | exit(1); | |
99 | } | |
100 | pw.getHeader()->id = d_idqueue.front(); | |
101 | d_idqueue.pop_front(); | |
102 | pw.getHeader()->rd = 0; | |
103 | pw.getHeader()->qr = 0; | |
104 | ||
105 | if(::sendto(d_socket, &*packet.begin(), packet.size(), 0, (struct sockaddr*)&domain.a, domain.a.getSocklen()) < 0) | |
106 | d_senderrors++; | |
107 | ||
108 | return pw.getHeader()->id; | |
109 | } | |
110 | ||
111 | bool receive(Identifier& id, DNSResult& dr) | |
112 | { | |
113 | if(waitForData(d_socket, 0, 500000) > 0) { | |
114 | char buf[512]; | |
115 | ComboAddress from; | |
116 | from.sin4.sin_family = AF_INET; | |
117 | socklen_t socklen=from.getSocklen(); | |
118 | int len = recvfrom(d_socket, buf, sizeof(buf),0, (struct sockaddr*)&from, &socklen); | |
119 | if(len < 0) { | |
120 | d_receiveerrors++; | |
121 | return 0; | |
122 | } | |
123 | else { | |
46d77a35 | 124 | d_received++; |
ca12836d | 125 | } |
126 | // parse packet, set 'id', fill out 'ip' | |
127 | ||
27c0050c | 128 | MOADNSParser mdp(false, string(buf, len)); |
ca12836d | 129 | if(!g_quiet) { |
a8d9bc94 | 130 | cout<<"Reply to question for qname='"<<mdp.d_qname<<"', qtype="<<DNSRecordContent::NumberToType(mdp.d_qtype)<<endl; |
ca12836d | 131 | cout<<"Rcode: "<<mdp.d_header.rcode<<", RD: "<<mdp.d_header.rd<<", QR: "<<mdp.d_header.qr; |
132 | cout<<", TC: "<<mdp.d_header.tc<<", AA: "<<mdp.d_header.aa<<", opcode: "<<mdp.d_header.opcode<<endl; | |
133 | } | |
134 | id = mdp.d_header.id; | |
135 | d_idqueue.push_back(id); | |
136 | dr.qclass = mdp.d_qclass; | |
137 | dr.content.clear(); | |
138 | dr.ttl=0; | |
139 | for(const auto& a : mdp.d_answers) { | |
140 | if(a.first.d_type == QType::TXT) { | |
141 | dr.content=a.first.d_content->getZoneRepresentation(); | |
142 | dr.ttl=a.first.d_ttl; | |
143 | } | |
144 | } | |
145 | if(dr.content.empty()) | |
146 | dr.content="RCode: "+RCode::to_s(mdp.d_header.rcode); | |
147 | return 1; | |
148 | } | |
149 | return 0; | |
150 | } | |
151 | ||
152 | void deliverTimeout(const Identifier& id) | |
153 | { | |
154 | if(!g_quiet) { | |
155 | cout<<"Timeout for id "<<id<<endl; | |
156 | } | |
157 | d_idqueue.push_back(id); | |
158 | } | |
159 | ||
160 | void deliverAnswer(NSQuery& domain, const DNSResult& dr, unsigned int usec) | |
161 | { | |
a8d9bc94 | 162 | cout<<domain.a.toString()<<"\t"<<domain.qname<<"\t"; |
ca12836d | 163 | for(const auto& n : domain.nsnames) |
a8d9bc94 | 164 | cout<<n<<","; |
ca12836d | 165 | cout<<"\t"<<domain.count<<"\t"<<dr.qclass<<'\t'<<dr.ttl<<": "<<dr.content<<endl; |
166 | ||
167 | if(dr.qclass==1 || toLower(dr.content).find("powerdns") != string::npos || dr.ttl==5) { | |
168 | auto f = d_res.find(domain.a); | |
169 | if(!f->second.isPowerDNS) { | |
170 | (*g_powerdns)<<domain.a.toString()<<'\t'<<domain.count<<'\t'; | |
171 | for(const auto& n : domain.nsnames) | |
a8d9bc94 | 172 | (*g_powerdns)<<n<<'\t'; |
ca12836d | 173 | (*g_powerdns)<<"\n"; |
174 | f->second.isPowerDNS=true; | |
175 | } | |
176 | ||
177 | } | |
178 | ||
179 | } | |
180 | unsigned int d_errors, d_nxdomains, d_nodatas, d_oks, d_unknowns; | |
46d77a35 | 181 | unsigned int d_received, d_receiveerrors, d_senderrors; |
ca12836d | 182 | map<ComboAddress, namecount, ComboAddress::addressOnlyLessThan>& d_res; |
183 | }; | |
184 | ||
185 | ||
186 | struct RESResult | |
187 | { | |
188 | vector<ComboAddress> addrs; | |
189 | uint16_t rcode; | |
190 | }; | |
191 | ||
192 | typedef DNSName RESQuery; | |
193 | ||
194 | struct SendReceiveRes | |
195 | { | |
196 | typedef int Identifier; | |
197 | typedef RESResult Answer; // ip | |
198 | int d_socket; | |
4e998d96 | 199 | std::deque<uint16_t> d_idqueue; |
ca12836d | 200 | map<DNSName, vector<ComboAddress>>& d_out; |
201 | SendReceiveRes(const ComboAddress& remote, map<DNSName,vector<ComboAddress>>& out) : d_out(out) | |
202 | { | |
203 | d_socket = socket(AF_INET, SOCK_DGRAM, 0); | |
204 | int val=1; | |
1ce8f718 AT |
205 | |
206 | if (setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) != 0) | |
207 | cerr<<"Failed to turn on SO_REUSEADDR: " << stringerror() << endl; | |
208 | if (connect(d_socket, (struct sockaddr*)&remote, remote.getSocklen()) != 0) | |
209 | throw DNSException("connect(" + remote.toStringWithPort() + ") failed: " + stringerror()); | |
ca12836d | 210 | for(unsigned int id =0 ; id < std::numeric_limits<uint16_t>::max(); ++id) |
211 | d_idqueue.push_back(id); | |
212 | } | |
213 | ||
214 | ~SendReceiveRes() | |
215 | { | |
216 | close(d_socket); | |
217 | } | |
218 | ||
219 | Identifier send(RESQuery& domain) | |
220 | { | |
221 | //cerr<<"Sending query for '"<<domain<<"'"<<endl; | |
222 | ||
223 | // send it, copy code from 'sdig' | |
224 | vector<uint8_t> packet; | |
225 | ||
226 | DNSPacketWriter pw(packet, domain, QType::A); | |
227 | ||
228 | if(d_idqueue.empty()) { | |
229 | cerr<<"Exhausted ids!"<<endl; | |
230 | exit(1); | |
231 | } | |
232 | pw.getHeader()->id = d_idqueue.front(); | |
233 | d_idqueue.pop_front(); | |
234 | pw.getHeader()->rd = 1; | |
235 | pw.getHeader()->qr = 0; | |
236 | ||
237 | if(::send(d_socket, &*packet.begin(), packet.size(), 0) < 0) { | |
a702a96c | 238 | cout<<"Error sending: "<<stringerror()<<endl; |
ca12836d | 239 | d_senderrors++; |
240 | } | |
241 | ||
242 | return pw.getHeader()->id; | |
243 | } | |
244 | ||
245 | bool receive(Identifier& id, RESResult& dr) | |
246 | { | |
247 | if(waitForData(d_socket, 0, 500000) > 0) { | |
248 | char buf[512]; | |
249 | ComboAddress from; | |
250 | from.sin4.sin_family = AF_INET; | |
251 | socklen_t socklen=from.getSocklen(); | |
252 | int len = recvfrom(d_socket, buf, sizeof(buf),0, (struct sockaddr*)&from, &socklen); | |
253 | if(len < 0) { | |
254 | d_receiveerrors++; | |
255 | return 0; | |
256 | } | |
257 | else { | |
46d77a35 | 258 | d_received++; |
ca12836d | 259 | } |
260 | // parse packet, set 'id', fill out 'ip' | |
261 | ||
27c0050c | 262 | MOADNSParser mdp(false, string(buf, len)); |
ca12836d | 263 | if(!g_quiet) { |
a8d9bc94 | 264 | cout<<"Reply to question for qname='"<<mdp.d_qname<<"', qtype="<<DNSRecordContent::NumberToType(mdp.d_qtype)<<endl; |
ca12836d | 265 | cout<<"Rcode: "<<mdp.d_header.rcode<<", RD: "<<mdp.d_header.rd<<", QR: "<<mdp.d_header.qr<<", answers: "<<mdp.d_answers.size(); |
266 | cout<<", TC: "<<mdp.d_header.tc<<", AA: "<<mdp.d_header.aa<<", opcode: "<<mdp.d_header.opcode<<endl; | |
267 | } | |
268 | id = mdp.d_header.id; | |
269 | d_idqueue.push_back(id); | |
270 | dr.rcode = mdp.d_header.rcode; | |
271 | dr.addrs.clear(); | |
272 | for(const auto& a : mdp.d_answers) { | |
273 | if(a.first.d_name != mdp.d_qname) | |
274 | continue; | |
275 | if(a.first.d_type == QType::A || a.first.d_type == QType::AAAA) { | |
276 | if(!g_quiet) | |
277 | cout<<a.first.d_content->getZoneRepresentation()<<endl; | |
278 | dr.addrs.push_back(getAddr(a.first)); | |
279 | } | |
280 | } | |
281 | ++g_count; | |
282 | return 1; | |
283 | } | |
284 | return 0; | |
285 | } | |
286 | ||
287 | void deliverTimeout(const Identifier& id) | |
288 | { | |
289 | if(!g_quiet) { | |
290 | cout<<"Timeout for id "<<id<<endl; | |
291 | } | |
292 | ++g_count; | |
293 | d_idqueue.push_back(id); | |
294 | } | |
295 | ||
296 | void deliverAnswer(DNSName& domain, const RESResult& dr, unsigned int usec) | |
297 | { | |
298 | d_out[domain]=dr.addrs; | |
299 | cout<<domain<<"\t"<<dr.rcode<<'\t'; | |
300 | for(const auto& a : dr.addrs) | |
301 | cout<<a.toString()<<'\t'; | |
302 | cout<<'\n'; | |
303 | } | |
304 | unsigned int d_errors, d_nxdomains, d_nodatas, d_oks, d_unknowns; | |
46d77a35 | 305 | unsigned int d_received, d_receiveerrors, d_senderrors; |
ca12836d | 306 | }; |
307 | ||
308 | ||
1ce8f718 | 309 | static void printStats() |
ca12836d | 310 | { |
311 | while(!g_stop) { | |
312 | sleep(1); | |
313 | cerr<<"\r"<<g_count; | |
314 | cerr.flush(); | |
315 | } | |
316 | cerr<<"\n"; | |
317 | } | |
318 | ||
1ce8f718 | 319 | static int parseZone(const std::string& str, unsigned int limit) |
ca12836d | 320 | { |
321 | ZoneParserTNG zpt(str); | |
45bf6885 | 322 | zpt.disableGenerate(); |
ca12836d | 323 | DNSResourceRecord rr; |
324 | ||
325 | std::thread stats(printStats); | |
326 | ||
327 | map<DNSName,unsigned int> nsnames; | |
328 | map<DNSName,set<ComboAddress,ComboAddress::addressOnlyLessThan> > addresses; | |
329 | ||
330 | ||
331 | while(zpt.get(rr)) { | |
332 | if(rr.qtype.getCode() == QType::NS) | |
333 | nsnames[DNSName(rr.content)]++; | |
334 | else if(rr.qtype.getCode() == QType::A || rr.qtype.getCode() == QType::AAAA) { | |
335 | DNSRecord dr(rr); | |
336 | addresses[rr.qname].insert(getAddr(dr, 53)); | |
337 | } | |
338 | ++g_count; | |
339 | if(g_count == limit) | |
340 | break; | |
341 | } | |
342 | g_stop=true; | |
343 | stats.join(); | |
344 | ||
345 | cout<<"Got "<<nsnames.size()<<" different nameserver names"<<endl; | |
346 | cout<<"Got at least one address for "<<addresses.size()<<" names"<<endl; | |
347 | ||
348 | ofstream ns(str+".nameservers"); | |
349 | ofstream needres(str+".needres"); | |
350 | for(const auto& a: nsnames) { | |
351 | ns<<a.first<<"\t"<<a.second<<"\t"; | |
352 | if(auto hit=rplookup(addresses, a.first)) { | |
353 | for(const auto& b : *hit) | |
354 | ns<<b.toString()<<"\t"; | |
355 | } | |
356 | else | |
357 | needres<<a.first<<"\n"; | |
358 | ns<<"\n"; | |
359 | } | |
360 | return 0; | |
361 | } | |
362 | ||
1ce8f718 | 363 | static int resolveNS(const std::string& fname) |
ca12836d | 364 | { |
365 | string line; | |
366 | ifstream needres(fname); | |
367 | if(!needres) | |
368 | unixDie("Unable to open file "+fname); | |
369 | vector<DNSName> tores; | |
370 | while(getline(needres,line)) { | |
371 | tores.push_back(DNSName(line)); | |
372 | } | |
373 | cerr<<"Going to resolve "<<tores.size()<<" names"<<endl; | |
374 | std::thread stats(printStats); | |
375 | map<DNSName, vector<ComboAddress>> output; | |
376 | SendReceiveRes sr(ComboAddress("192.168.1.2", 53), output); | |
377 | Inflighter<vector<DNSName>, SendReceiveRes> inflighter(tores, sr); | |
378 | inflighter.d_maxInFlight = 1000; | |
379 | inflighter.d_timeoutSeconds = 3; | |
380 | inflighter.d_burst = 100; | |
381 | for(;;) { | |
382 | try { | |
383 | inflighter.run(); | |
384 | break; | |
385 | } | |
386 | catch(std::exception& e) { | |
387 | cerr<<"Caught exception: "<<e.what()<<endl; | |
388 | } | |
389 | } | |
390 | g_stop=true; | |
391 | stats.join(); | |
392 | return EXIT_SUCCESS; | |
393 | } | |
394 | ||
1ce8f718 | 395 | static void readRESNames(const std::string& fname, map<DNSName, vector<ComboAddress>>& addrs) |
ca12836d | 396 | { |
397 | ifstream ifs(fname); | |
398 | if(!ifs) | |
bb99bcf1 | 399 | unixDie("Reading resolved names from "+fname+": "+stringerror()); |
ca12836d | 400 | vector<string> parts; |
401 | string line; | |
402 | addrs.clear(); | |
403 | while(getline(ifs, line)) { | |
404 | parts.clear(); | |
405 | stringtok(parts, line,"\t"); | |
406 | for(unsigned int n=2; n < parts.size(); ++n) | |
407 | addrs[DNSName(parts[0])].push_back(ComboAddress(parts[n], 53)); | |
408 | } | |
409 | //EARTH.DOMAINS.SHELTEK.CA. 0 67.15.253.219 67.15.47.188 67.15.253.252 67.15.253.251 67.15.47.189 67.15.253.220 | |
410 | cerr<<"Got "<<addrs.size()<<" resolved nameserver names from file"<<endl; | |
411 | ||
412 | } | |
413 | ||
414 | int main(int argc, char**argv) | |
415 | try | |
416 | { | |
417 | g_quiet=true; | |
418 | reportAllTypes(); | |
419 | string mode=argv[1]; | |
420 | if(mode == "parse-zone") { | |
421 | unsigned int limit = 0; | |
422 | if(argc > 3) | |
423 | limit = atoi(argv[3]); | |
424 | ||
425 | return parseZone(argv[2], limit); | |
426 | } | |
427 | else if(mode=="resolve-ns") { | |
428 | return resolveNS(string(argv[2])+".needres"); | |
429 | } | |
430 | else if(mode=="scan-ns") { | |
431 | ifstream ns(string(argv[2])+".nameservers"); | |
2bbc9eb0 | 432 | g_powerdns = std::make_unique<std::ofstream>(string(argv[2]) + ".powerdns"); |
ca12836d | 433 | string line; |
434 | int count=0; | |
435 | vector<string> parts; | |
436 | ||
437 | struct NSCount | |
438 | { | |
439 | unsigned int count{0}; | |
440 | vector<ComboAddress> addrs; | |
441 | }; | |
442 | map<DNSName, NSCount> stats; | |
443 | NSCount nscount; | |
444 | // NS1.IHOST2000.COM. 9 162.251.82.122 162.251.82.123 162.251.82.250 162.251.82.251 | |
445 | while(getline(ns, line)) { | |
446 | ++count; | |
447 | parts.clear(); | |
448 | stringtok(parts, line,"\t"); | |
449 | nscount.count=atoi(parts[1].c_str()); | |
450 | nscount.addrs.clear(); | |
451 | for(unsigned int n = 2; n < parts.size(); ++n) | |
452 | nscount.addrs.push_back(ComboAddress(parts[n], 53)); | |
453 | stats.insert({DNSName(parts[0]), nscount}); | |
454 | } | |
455 | cerr<<"Had "<<count<<" lines from summary"<<endl; | |
456 | ||
457 | map<DNSName, vector<ComboAddress>> lookedup; | |
458 | readRESNames(argv[2]+string(".resolved"), lookedup); | |
459 | ||
460 | map<ComboAddress, namecount, ComboAddress::addressOnlyLessThan> pure; | |
461 | ||
462 | unsigned int noaddrs=0; | |
463 | for(const auto& s : stats) { | |
464 | auto ptr = &s.second.addrs; | |
465 | if(ptr->empty()) { | |
466 | if(lookedup.count(s.first)) { | |
467 | ptr = &lookedup[s.first]; | |
468 | } | |
469 | else { | |
470 | //cout<<"Have no address for "<<s.first.toString()<<endl; | |
471 | noaddrs++; | |
472 | } | |
473 | } | |
474 | ||
475 | for(const auto& a : *ptr) { | |
476 | pure[a].count += s.second.count; | |
477 | pure[a].names.insert(s.first); | |
478 | } | |
479 | } | |
480 | ||
481 | cerr<<"Have "<<pure.size()<<" IP addresses to query, "<<noaddrs<<" names w/o address"<<endl; | |
482 | SendReceive sr(pure); | |
483 | vector<NSQuery> domains; | |
484 | ||
485 | Inflighter<vector<NSQuery>, SendReceive> inflighter(domains, sr); | |
486 | inflighter.d_maxInFlight = 1000; | |
487 | inflighter.d_timeoutSeconds = 3; | |
488 | inflighter.d_burst = 100; | |
489 | ||
490 | for(const auto& p : pure) { | |
491 | NSQuery nsq; | |
492 | nsq.a=p.first; | |
493 | nsq.nsnames = p.second.names; | |
494 | nsq.count = p.second.count; | |
495 | ||
496 | nsq.qname=DNSName("version.bind"); | |
497 | domains.push_back(nsq); | |
498 | nsq.qname=DNSName("id.server"); | |
499 | domains.push_back(nsq); | |
500 | nsq.qname=DNSName("bind.version"); | |
501 | domains.push_back(nsq); | |
502 | } | |
503 | ||
504 | sort(domains.begin(), domains.end(), [](const NSQuery& a, const NSQuery& b) { return b.count < a.count; }); | |
505 | for(;;) { | |
506 | try { | |
507 | inflighter.run(); | |
508 | break; | |
509 | } | |
510 | catch(std::exception& e) { | |
511 | cerr<<"Caught exception: "<<e.what()<<endl; | |
512 | } | |
513 | } | |
514 | } | |
515 | else if(mode=="score-ns") { | |
516 | std::unordered_set<DNSName> powerdns; | |
517 | ifstream ifs(string(argv[2])+".powerdns"); | |
518 | string line; | |
519 | vector<string> parts; | |
520 | while(getline(ifs,line)) { | |
521 | // 64.96.240.53 1234 NS1.UNIREGISTRYMARKET.LINK. NS1.INTERNETTRAFFIC.COM. BUY.INTERNETTRAFFIC.COM. NS3.SECUREDOFFERS.COM. NS3.GI.NET. NS3.IT.GI.NET. NS3.EASILY.NET. | |
522 | parts.clear(); | |
523 | stringtok(parts, line); | |
524 | for(unsigned int n=2; n < parts.size(); ++n) | |
525 | powerdns.insert(DNSName(parts[n])); | |
526 | } | |
527 | cerr<<"Have "<<powerdns.size()<<" known NS names that are PowerDNS"<<endl; | |
528 | ZoneParserTNG zpt(argv[2]); | |
45bf6885 | 529 | zpt.disableGenerate(); |
ca12836d | 530 | DNSResourceRecord rr; |
531 | ||
ca12836d | 532 | set<DNSName> seen, pdnsdomains; |
533 | int count=0; | |
534 | while(zpt.get(rr)) { | |
535 | if(!seen.count(rr.qname)) { | |
536 | seen.insert(rr.qname); | |
537 | } | |
538 | if(rr.qtype.getCode() == QType::NS && powerdns.count(DNSName(rr.content)) && !pdnsdomains.count(DNSName(rr.qname))) { | |
ca12836d | 539 | pdnsdomains.insert(DNSName(rr.qname)); |
540 | } | |
541 | if(!(count%100000)) { | |
542 | cerr<<"\rUnique domains: "<<seen.size()<<", PowerDNS domains: "<<pdnsdomains.size()<<" ("<<(pdnsdomains.size()*100.0/seen.size())<<"%)"; | |
543 | } | |
544 | count++; | |
545 | } | |
546 | cerr<<"\n"; | |
547 | } | |
548 | else { | |
549 | cerr<<"Unknown mode "<<argv[1]<<endl; | |
550 | } | |
551 | // cout<<g_mtracer->topAllocatorsString(20)<<endl; | |
552 | } | |
553 | catch(PDNSException& pe) { | |
554 | cerr<<"Fatal error: "<<pe.reason<<endl; | |
555 | } |