#!/usr/bin/env perl
# dnsperf.pl  DNS server performance test program.
#             Graham Jenkins <grahjenk@cpan.org> Revised: 2020-06-08

=head1 NAME

dnsperf - a tool for comparing DNS servers

=head1 USAGE

dnsperf [-query=type] [-timeout=secs] duration

A set of DNS queries is performed for the 'duration' period in seconds
using each of the servers shown at the end of this program, and the
success counts for each server are then listed in order.

Default values for 'query' and 'timeout' are "A" and "2".

=head1 SCRIPT CATEGORIES

UNIX/System_administration
Networking

=head1 AUTHOR

Graham Jenkins <grahjenk@cpan.org>

=head1 README

A simple tool for comparing the response times of designated DNS servers.

=head1 COPYRIGHT

Copyright (c) 2020 Graham Jenkins. All rights reserved.
This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

=cut

use strict;
use warnings;
use File::Basename;
use Getopt::Long;
use Config;
use File::Temp qw/tempdir/;
use File::Fetch;
use Net::Nslookup;
use Time::HiRes qw(time);
use vars qw($VERSION);
$VERSION=1.03;

# Collect options, check usage
my ($type,$secs)=("A",2);
GetOptions("query=s"=>\$type,"timeout=i"=>\$secs);
die "Usage: ".basename($0)." [-query=type] [-timeout=secs] duration\n".
    " e.g.: ".basename($0)." -query=A -timeout=1 3\n"
  if( ($#ARGV!=0) || ($ARGV[0]!~m/\d+$/) );

# Get a list of the most popular websites
my $dir=tempdir(CLEANUP=>1 );
my $ff=File::Fetch->new(uri =>
  "https://moz.com/top-500/download/?table=top500Domains");
my $where=$ff->fetch( to => "$dir" ) or die $ff->error;
open(FILE,$where);
my @lines;
my $i=0;
while ( my $record=<FILE> ) {
  my ($d1,$d2)=split(",",$record);
  $d2=~s/\"//g;
  $lines[$i++]=$d2
}

# Swallow STDERR, autoflush STDOUT
my $null;
if ( $Config{osname} =~ /Win(32|64)$/i ) {$null="NUL"} else {$null="/dev/null"}
open(STDERR,">$null");
$|++;

# Test each server in turn by making 'count' queries to it
my ($key,$address,,%success,$clock0,$result);
print "Generating results ";
while ( <DATA> ) {
  chomp;
  $key=$_;
  if ( $key=~m/\#/ ) { next }
  ($address,)=split(/\s+/);
  $success{$key}=0;
  my $i=1;
  $clock0=time();
  while (time() < $clock0+$ARGV[0]) {
    if ( $i>$#lines ) { $i=1 }
    my $host=$lines[$i++];
    if ( substr($address,0,1) eq "L") {
      $result=nslookup(host=>$host,type=>$type,timeout=>$secs)
    } else {
      $result=nslookup(host=>$host,type=>$type,timeout=>$secs,server=>$address)
    }
    if ( defined($result) ) { $success{$key}+=1 }
  }
  print "."
}

# Sort and print in ascending order of average query time
my @sorted= sort {$success{$b} <=> $success{$a}} keys(%success);
print "\nCount\n-----\n";
foreach my $line (@sorted) {
  my $a=$success{$line};
  print substr("     ",0,5-length($a)).$a," ",$line,"\n"
}

__END__
8.8.8.8         Google
1.1.1.1         Cloudflare
9.9.9.9         Quad9
Local-Cache     ==
# 1.2.3.4       Insert your local provider-DNS-server(s) here
