#!/usr/bin/perl use strict; use warnings; use threads; use Net::DNS; use NetAddr::IP; use Thread::Queue; use Getopt::Long; my %options = ( threads => 20, quiet => 0, timeout => 3, search => 'www.google.com', ); GetOptions( 'threads=i' => \$options{threads}, 'quiet' => \$options{quiet}, 'timeout=i' => \$options{timeout}, 'search=s' => \$options{search}, ); my @ips; if ($#ARGV eq -1){ while (my $range = ){ parse_range($range); } } else{ while (my $range = shift){ parse_range($range); } } if ($#ips eq -1){ die "E: need a CIDR range"; } sub parse_range { my $range = shift; my $n = NetAddr::IP->new($range); foreach my $ip (@{$n->hostenumref}){ push @ips, $ip->addr; } } our $THREADS = ($options{threads} >= $#ips) ? $#ips+1 : $options{threads}; my $Qwork = new Thread::Queue; my $Qresults = new Thread::Queue; ## Create the pool of workers my @pool = map{ threads->create(\&worker, $Qwork, $Qresults) } 1 .. $THREADS; ## Get the work items (from somewhere) ## and queue them up for the workers while (my $workItem = getWorkItems()) { $Qwork->enqueue($workItem); } ## Tell the workers there are no more work items $Qwork->enqueue((undef) x $THREADS); ## Process the results as they become available ## until all the workers say they are finished. for (1 .. $THREADS) { while (my $result = $Qresults->dequeue) { print "$result\n" unless ($options{quiet}); } } ## Clean up the threads $_->join for @pool; sub getWorkItems { return shift @ips; } sub worker { my $tid = threads->tid; my ($Qwork, $Qresults) = @_; while (my $work = $Qwork->dequeue) { my $result; my $server = Net::DNS::Resolver->new( nameservers => [$work], recurse => 1, #debug => 1, udp_timeout => $options{timeout}, retry => 1, ); my $query = $server->search($options{search}); $result = "$work ... "; if ($query) { $result .= 'OPEN'; } else{ $result .= 'NO RESPONSE'; } $Qresults->enqueue($result); } $Qresults->enqueue(undef); ## Signal this thread is finished }