From: Remi Gacogne Date: Fri, 22 Sep 2023 09:05:46 +0000 (+0200) Subject: dnsscope: Add a `--port` option to select a custom port X-Git-Tag: rec-5.0.0-alpha2~36^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e9ca1b280b02b2ab12d11934cce0b18684b4d076;p=thirdparty%2Fpdns.git dnsscope: Add a `--port` option to select a custom port --- diff --git a/pdns/dnsscope.cc b/pdns/dnsscope.cc index 06c45dd4e2..5e52d407a5 100644 --- a/pdns/dnsscope.cc +++ b/pdns/dnsscope.cc @@ -146,6 +146,7 @@ try ("filter-name,f", po::value(), "Do statistics only for queries within this domain") ("load-stats,l", po::value()->default_value(""), "if set, emit per-second load statistics (questions, answers, outstanding)") ("no-servfail-stats", "Don't include servfails in response time stats") + ("port", po::value()->default_value(0), "The source and destination port to consider. Default is looking at packets from and to ports 53 and 5300") ("servfail-tree", "Figure out subtrees that generate servfails") ("stats-dir", po::value()->default_value("."), "Directory where statistics will be saved") ("write-failures,w", po::value()->default_value(""), "if set, write weird packets to this PCAP file") @@ -217,6 +218,7 @@ try std::unordered_set requestors, recipients, rdnonra; typedef vector > pcounts_t; pcounts_t pcounts; + const uint16_t port = g_vm["port"].as(); OPTRecordContent::report(); for(unsigned int fno=0; fno < files.size(); ++fno) { @@ -228,164 +230,179 @@ try EDNSOpts edo; while(pr.getUDPPacket()) { - if((ntohs(pr.d_udp->uh_dport)==5300 || ntohs(pr.d_udp->uh_sport)==5300 || - ntohs(pr.d_udp->uh_dport)==53 || ntohs(pr.d_udp->uh_sport)==53) && - pr.d_len > 12) { - try { - if((pr.d_ip->ip_v == 4 && !doIPv4) || (pr.d_ip->ip_v == 6 && !doIPv6)) - continue; - if(pr.d_ip->ip_v == 4) { - uint16_t frag = ntohs(pr.d_ip->ip_off); - if((frag & IP_MF) || (frag & IP_OFFMASK)) { // more fragments or IS a fragment - fragmented++; - continue; - } - } - uint16_t qtype; - DNSName qname((const char*)pr.d_payload, pr.d_len, 12, false, &qtype); - struct dnsheader header; - memcpy(&header, (struct dnsheader*)pr.d_payload, 12); - - if(haveRDFilter && header.rd != rdFilter) { - rdFilterMismatch++; - continue; - } - - if(!filtername.empty() && !qname.isPartOf(filtername)) { - nameMismatch++; + if (pr.d_len <= 12) { + // non-DNS ip + nonDNSIP++; + continue; + } + if (port > 0 && + (ntohs(pr.d_udp->uh_dport) != port && ntohs(pr.d_udp->uh_sport) != port)) { + // non-DNS ip + nonDNSIP++; + continue; + } + + if (port == 0 && + (ntohs(pr.d_udp->uh_dport) != 5300 && ntohs(pr.d_udp->uh_sport) != 5300 && + ntohs(pr.d_udp->uh_dport) != 53 && ntohs(pr.d_udp->uh_sport) != 53)) { + // non-DNS ip + nonDNSIP++; + continue; + } + + try { + if ((pr.d_ip->ip_v == 4 && !doIPv4) || (pr.d_ip->ip_v == 6 && !doIPv6)) { + continue; + } + + if (pr.d_ip->ip_v == 4) { + uint16_t frag = ntohs(pr.d_ip->ip_off); + if((frag & IP_MF) || (frag & IP_OFFMASK)) { // more fragments or IS a fragment + fragmented++; continue; } + } + uint16_t qtype; + DNSName qname((const char*)pr.d_payload, pr.d_len, 12, false, &qtype); + struct dnsheader header; + memcpy(&header, (struct dnsheader*)pr.d_payload, 12); + + if(haveRDFilter && header.rd != rdFilter) { + rdFilterMismatch++; + continue; + } + + if(!filtername.empty() && !qname.isPartOf(filtername)) { + nameMismatch++; + continue; + } + + if(!header.qr) { + uint16_t udpsize, z; + if(getEDNSUDPPayloadSizeAndZ((const char*)pr.d_payload, pr.d_len, &udpsize, &z)) { + edns++; + if(z & EDNSOpts::DNSSECOK) + dnssecOK++; + if(header.cd) + dnssecCD++; + if(header.ad) + dnssecAD++; + } + } + + if(pr.d_ip->ip_v == 4) + ++ipv4DNSPackets; + else + ++ipv6DNSPackets; - if(!header.qr) { - uint16_t udpsize, z; - if(getEDNSUDPPayloadSizeAndZ((const char*)pr.d_payload, pr.d_len, &udpsize, &z)) { - edns++; - if(z & EDNSOpts::DNSSECOK) - dnssecOK++; - if(header.cd) - dnssecCD++; - if(header.ad) - dnssecAD++; + if(pr.d_pheader.ts.tv_sec != lastsec) { + LiveCounts lc; + if(lastsec) { + lc.questions = queries; + lc.answers = answers; + lc.outstanding = liveQuestions(); + + LiveCounts diff = lc - lastcounts; + pcounts.emplace_back(pr.d_pheader.ts.tv_sec, diff); + } + lastsec = pr.d_pheader.ts.tv_sec; + lastcounts = lc; + } + + if(lowestTime) { lowestTime = min((time_t)lowestTime, (time_t)pr.d_pheader.ts.tv_sec); } + else { lowestTime = pr.d_pheader.ts.tv_sec; } + highestTime=max((time_t)highestTime, (time_t)pr.d_pheader.ts.tv_sec); + + QuestionIdentifier qi=QuestionIdentifier::create(pr.getSource(), pr.getDest(), header, qname, qtype); + + if(!header.qr) { // question + // cout<<"Query "<ip_v == 4) - ++ipv4DNSPackets; - else - ++ipv6DNSPackets; + if(header.ra) { + ComboAddress rem = pr.getDest(); + rem.sin4.sin_port=0; + recipients.insert(rem); + } - if(pr.d_pheader.ts.tv_sec != lastsec) { - LiveCounts lc; - if(lastsec) { - lc.questions = queries; - lc.answers = answers; - lc.outstanding = liveQuestions(); + QuestionData& qd=statmap[qi]; + if(!qd.d_qcount) { + // cout<<"Untracked answer: "<write(); - parsefail++; - continue; - } + if(!qd.d_qcount || qd.d_qcount == qd.d_answercount) { + // cout<<"Clearing state for "<write(); + parsefail++; + continue; } } - cout<<"PCAP contained "<