From: bert hubert Date: Tue, 25 Jun 2013 08:10:28 +0000 (+0200) Subject: initial non-working dnsdist X-Git-Tag: rec-3.6.0-rc1~634 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=24d5cb005e2c5bd53756adf65eb50d65c041dd40;p=thirdparty%2Fpdns.git initial non-working dnsdist --- diff --git a/pdns/Makefile.am b/pdns/Makefile.am index 2c538a552d..07e4418148 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -39,7 +39,7 @@ sbin_PROGRAMS = pdns_server bin_PROGRAMS = pdns_control pdnssec dnsreplay endif -EXTRA_PROGRAMS=pdns_recursor sdig dnstcpbench tsig-tests speedtest pdns_control dnsscope dnsgram \ +EXTRA_PROGRAMS=pdns_recursor sdig dnstcpbench dnsdist tsig-tests speedtest pdns_control dnsscope dnsgram \ testrunner \ toysdig dnsdemog dnswasher dnsscan nproxy notify pdnssec dnsbulktest nsec3dig # dnslabel # tcptorture @@ -148,6 +148,14 @@ dnstcpbench_SOURCES=dnstcpbench.cc sstuff.hh dnsparser.cc dnsparser.hh dnsrecord dnstcpbench_LDFLAGS=$(BOOST_PROGRAM_OPTIONS_LDFLAGS) dnstcpbench_LDADD=$(BOOST_PROGRAM_OPTIONS_LIBS) + +dnsdist_SOURCES=dnsdist.cc sstuff.hh dnsparser.cc dnsparser.hh dnsrecords.cc dnswriter.cc dnslabeltext.cc dnswriter.hh \ + misc.cc misc.hh rcpgenerator.cc rcpgenerator.hh base64.cc base64.hh unix_utility.cc \ + logger.cc statbag.cc qtype.cc sillyrecords.cc nsecrecords.cc base32.cc +dnsdist_LDFLAGS=$(BOOST_PROGRAM_OPTIONS_LDFLAGS) +dnsdist_LDADD=$(BOOST_PROGRAM_OPTIONS_LIBS) + + nsec3dig_SOURCES=nsec3dig.cc sstuff.hh dnsparser.cc dnsparser.hh dnsrecords.cc dnswriter.cc dnslabeltext.cc \ dnswriter.hh dnssecinfra.cc \ misc.cc misc.hh rcpgenerator.cc rcpgenerator.hh base64.cc base64.hh unix_utility.cc \ diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc new file mode 100644 index 0000000000..96e7b740df --- /dev/null +++ b/pdns/dnsdist.cc @@ -0,0 +1,238 @@ +/* + PowerDNS Versatile Database Driven Nameserver + Copyright (C) 2002-2013 PowerDNS.COM BV + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "dnsparser.hh" +#include "sstuff.hh" +#include "misc.hh" +#include "dnswriter.hh" +#include "dnsrecords.hh" +#include "statbag.hh" +#include +#include +#include + +StatBag S; +namespace po = boost::program_options; +po::variables_map g_vm; +bool g_verbose; +bool g_onlyTCP; +bool g_tcpNoDelay; +unsigned int g_timeoutMsec; +AtomicCounter g_networkErrors, g_otherErrors, g_OK, g_truncates, g_authAnswers, g_timeOuts; +ComboAddress g_dest; + +/* On Linux, run echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle + to prevent running out of free TCP ports */ + +struct BenchQuery +{ + BenchQuery(const std::string& qname_, uint16_t qtype_) : qname(qname_), qtype(qtype_), udpMsec(0), tcpMsec(0) {} + BenchQuery(){} + std::string qname; + uint16_t qtype; + uint16_t udpMsec, tcpMsec; +}; + + +void doQuery(BenchQuery* q) +try +{ + vector packet; + DNSPacketWriter pw(packet, q->qname, q->qtype); + int res; + string reply; + + if(!g_onlyTCP) { + Socket udpsock((AddressFamily)g_dest.sin4.sin_family, Datagram); + + udpsock.sendTo(string((char*)&*packet.begin(), (char*)&*packet.end()), g_dest); + ComboAddress origin; + res = waitForData(udpsock.getHandle(), 0, 1000 * g_timeoutMsec); + if(res < 0) + throw NetworkError("Error waiting for response"); + if(!res) { + g_timeOuts++; + return; + } + + udpsock.recvFrom(reply, origin); + MOADNSParser mdp(reply); + if(!mdp.d_header.tc) + return; + g_truncates++; + } + + Socket sock((AddressFamily)g_dest.sin4.sin_family, Stream); + int tmp=1; + if(setsockopt(sock.getHandle(),SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) + throw runtime_error("Unable to set socket reuse: "+string(strerror(errno))); + + if(g_tcpNoDelay && setsockopt(sock.getHandle(), IPPROTO_TCP, TCP_NODELAY,(char*)&tmp,sizeof tmp)<0) + throw runtime_error("Unable to set socket no delay: "+string(strerror(errno))); + + sock.connect(g_dest); + uint16_t len = htons(packet.size()); + string tcppacket((char*)& len, 2); + tcppacket.append((char*)&*packet.begin(), (char*)&*packet.end()); + + sock.writen(tcppacket); + + res = waitForData(sock.getHandle(), 0, 1000 * g_timeoutMsec); + if(res < 0) + throw NetworkError("Error waiting for response"); + if(!res) { + g_timeOuts++; + return; + } + + if(sock.read((char *) &len, 2) != 2) + throw AhuException("tcp read failed"); + + len=ntohs(len); + char *creply = new char[len]; + int n=0; + int numread; + while(n g_queries; + + +static void* worker(void*) +{ + for(;;) { + unsigned int pos = g_pos++; + if(pos >= g_queries.size()) + break; + + doQuery(&g_queries[pos]); // this is safe as long as nobody *inserts* to g_queries + } + return 0; +} + +int main(int argc, char** argv) +try +{ + po::options_description desc("Allowed options"), hidden, alloptions; + desc.add_options() + ("help,h", "produce help message") + ("verbose,v", "be verbose") + ("udp-first,u", "try UDP first") + ("tcp-no-delay", po::value()->default_value(true), "use TCP_NODELAY socket option") + ("timeout-msec", po::value()->default_value(10), "wait for this amount of milliseconds for an answer") + ("workers", po::value()->default_value(100), "number of parallel workers"); + + + hidden.add_options() + ("remote-host", po::value(), "remote-host") + ("remote-port", po::value()->default_value(53), "remote-port"); + alloptions.add(desc).add(hidden); + + po::positional_options_description p; + p.add("remote-host", 1); + p.add("remote-port", 1); + + po::store(po::command_line_parser(argc, argv).options(alloptions).positional(p).run(), g_vm); + po::notify(g_vm); + + if(g_vm.count("help")) { + cout << desc<(); + + g_onlyTCP = !g_vm.count("udp-first"); + g_verbose = g_vm.count("verbose"); + g_timeoutMsec = g_vm["timeout-msec"].as(); + + reportAllTypes(); + + if(g_vm["remote-host"].empty()) { + cerr<<"Syntax: tcpbench remote [port] < queries"<().c_str(), g_vm["remote-port"].as()); + + unsigned int numworkers=g_vm["workers"].as(); + + if(g_verbose) { + cout<<"Sending queries to: "< q; + string line; + while(stringfgets(fp, line)) { + trim_right(line); + q=splitField(line, ' '); + g_queries.push_back(BenchQuery(q.first, DNSRecordContent::TypeToNumber(q.second))); + } + fclose(fp); + + for(unsigned int n = 0; n < numworkers; ++n) { + pthread_create(&workers[n], 0, worker, 0); + } + for(unsigned int n = 0; n < numworkers; ++n) { + void* status; + pthread_join(workers[n], &status); + } + cout<<"OK: "<