144 lines
3.3 KiB
Perl
144 lines
3.3 KiB
Perl
#!/usr/bin/perl
|
|
# $Id: mresolv 1815 2020-10-14 21:55:18Z willem $
|
|
|
|
=head1 NAME
|
|
|
|
mresolv - Perform multiple DNS lookups in parallel
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
B<mresolv> S<[ B<-d> ]> S<[ B<-n> I<number> ]> S<[ B<-t> I<timeout> ]>
|
|
S<[ I<filename>... ]>
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
B<mresolv> performs multiple DNS lookups in parallel. Names to query
|
|
are read from the list of files given on the command line, or from the
|
|
standard input.
|
|
|
|
=head1 OPTIONS
|
|
|
|
=over 4
|
|
|
|
=item B<-d>
|
|
|
|
Turn on debugging output.
|
|
|
|
=item B<-n> I<number>
|
|
|
|
Set the number of queries to have outstanding at any time.
|
|
|
|
=item B<-t> I<timeout>
|
|
|
|
Set the timeout in seconds. If no replies are received for this
|
|
amount of time, all outstanding queries will be flushed and new
|
|
names will be read from the input stream.
|
|
|
|
=back
|
|
|
|
=head1 COPYRIGHT
|
|
|
|
Copyright (c) 1997-2000 Michael Fuhr. All rights reserved.
|
|
|
|
=head1 SEE ALSO
|
|
|
|
L<perl(1)>, L<axfr>, L<check_soa>, L<check_zone>, L<mx>, L<perldig>,
|
|
L<Net::DNS>
|
|
|
|
=cut
|
|
|
|
use strict;
|
|
use warnings;
|
|
use Net::DNS;
|
|
use IO::Select;
|
|
use Getopt::Std;
|
|
use vars qw($opt_d $opt_n $opt_t);
|
|
|
|
local $| = 1;
|
|
|
|
$opt_n = 32; # number of requests to have outstanding at any time
|
|
$opt_t = 15; # timeout (seconds)
|
|
|
|
getopts("dn:t:");
|
|
|
|
my $res = Net::DNS::Resolver->new;
|
|
my $sel = IO::Select->new;
|
|
my $eof = 0;
|
|
|
|
while (1) {
|
|
my $name;
|
|
my $sock;
|
|
|
|
#----------------------------------------------------------------------
|
|
# Read names until we've filled our quota of outstanding requests.
|
|
#----------------------------------------------------------------------
|
|
|
|
while (!$eof && $sel->count < $opt_n) {
|
|
print "DEBUG: reading..." if defined $opt_d;
|
|
$name = <>;
|
|
unless ($name) {
|
|
print "EOF.\n" if defined $opt_d;
|
|
$eof = 1;
|
|
last;
|
|
}
|
|
chomp $name;
|
|
$sock = $res->bgsend($name);
|
|
$sel->add($sock);
|
|
print "name = $name, outstanding = ", $sel->count, "\n"
|
|
if defined $opt_d;
|
|
}
|
|
|
|
#----------------------------------------------------------------------
|
|
# Wait for any replies. Remove any replies from the outstanding pool.
|
|
#----------------------------------------------------------------------
|
|
|
|
my @ready;
|
|
my $timed_out = 1;
|
|
|
|
print "DEBUG: waiting for replies\n" if defined $opt_d;
|
|
|
|
for (@ready = $sel->can_read($opt_t);
|
|
@ready;
|
|
@ready = $sel->can_read(0)) {
|
|
|
|
$timed_out = 0;
|
|
|
|
print "DEBUG: replies received: ", scalar @ready, "\n"
|
|
if defined $opt_d;
|
|
|
|
foreach my $sock (@ready) {
|
|
print "DEBUG: handling a reply\n" if defined $opt_d;
|
|
$sel->remove($sock);
|
|
my $ans = $res->bgread($sock);
|
|
next unless $ans;
|
|
my $rr;
|
|
foreach my $rr ($ans->answer) {
|
|
$rr->print;
|
|
}
|
|
}
|
|
}
|
|
|
|
#----------------------------------------------------------------------
|
|
# If we timed out waiting for replies, remove all entries from the
|
|
# outstanding pool.
|
|
#----------------------------------------------------------------------
|
|
|
|
if ($timed_out) {
|
|
print "DEBUG: timeout: clearing the outstanding pool.\n"
|
|
if defined $opt_d;
|
|
my $sock;
|
|
foreach my $sock ($sel->handles) {
|
|
$sel->remove($sock);
|
|
}
|
|
}
|
|
|
|
print "DEBUG: outstanding = ", $sel->count, ", eof = $eof\n"
|
|
if defined $opt_d;
|
|
|
|
#----------------------------------------------------------------------
|
|
# We're done if there are no outstanding queries and we've read EOF.
|
|
#----------------------------------------------------------------------
|
|
|
|
last if ($sel->count == 0) && $eof;
|
|
}
|