#!/usr/bin/perl # # nscan # ## use Getopt::Long; use POSIX qw(strftime); use Time::Local; use FindBin qw[$Bin]; $host = "/usr/bin/host"; # the core of our program sub domainlist { my $domain; my @presorted; my @output; my $pid; ($domain) = @_; exitclean("Could not fork!: $!") unless defined ($pid = open(HOSTPROC,"-|")); if ($pid) # parent process { while() { if (/(\w*\.$domain)/) { push @presorted,lc($1); } } close(HOSTPROC) or debugprint("Child process exited with: $?"); } else { # child process exec($host,"-l","-a",$domain) or exitclean("Could not execute $host: $!"); } @presorted = sort @presorted; $prev='noprevyet'; @output=grep($_ ne $prev && ($prev = $_),@presorted); return @output; } # signal catching sub sig_catch { my $signame = shift; print "\nRecieved SIG$signame, exiting...\n"; exit 2; } # our alternative to 'die' sub exitclean { my ($msg) = @_; print "$msg\n"; exit 2; } # show program usage sub usage { print "Usage: $0 [options] -t \n"; print "\noptions:\n"; print "\t-t -- the domain you want to scan.\n"; print "\t-d [directory] -- directory to put domain maps.\n"; print "\t-debug -- show debug information.\n"; print "\n\n"; exit 2; } sub debugprint { ($msg) = @_; print "[debug] $msg\n" unless (!$debug); } # # Start the main program # $SIG{INT}=\&sig_catch; $start_time = time; &GetOptions("debug", \$debug, "t:s",\$target, "d:s", \$directory); # make sure all of our input is ok if ($target eq "") { usage(); } if ($directory eq "") { printf("No output directory defined, using '$Bin'!\n"); $directory=$Bin; } else { if (-d $directory) { printf("Using directory: %s\n",$directory); } else { if (mkdir($directory,0755)) { printf("Created output directory: %s\n",$directory); } else { exitclean("Could not create output directory!: $!"); } } } chdir($directory) || exitclean("Could not change to output directory: $!"); %master = (); $level++; $count = 0; $target = lc($target); print "TARGET = $target.dom\n" unless -e "$target.dom"; if (-e "$target.dom") { printf("There is a domain file for the domain '%s'\n",$target); open(DOM,"<$target.dom") || exitclean("Could not open domain file: $!"); while($host=()) { chomp($host); push @targets,$host; } $master{$target} = @targets; close(DOM); printf("Loaded %d hosts from $target.dom\n",scalar(@targets)); @targets = (); } else { printf("Creating initial domain list for: %s\n",$target); $master{$target} = [(domainlist($target))]; @targets = (); @targets = @{$master{$target}}; open (DOM,">>$target.dom") || die ("Couldnt create domain map for top domain: $!"); foreach $t (@targets) { print DOM "$t\n"; } close(DOM); } debugprint("[ -- starting recursive zone transfers -- ]"); $oldcount = 1; while ($oldcount ne $count) { $oldcount = $count; foreach $key (keys(%master)) { @targets = (); @targets = @{$master{$key}}; debugprint(scalar(@targets) . " targets in domain $key"); foreach $t (@targets) { if ($master{$t} eq "") { debugprint("[$count] -- scanning $t"); $master{$t} = [(domainlist($t))]; $count++; # save domain file @hosts = (); @hosts = @{$master{$t}}; if (scalar(@hosts) != 0) { open (DOM,">>$t.dom") || die "Cant open $t.dom for writing: $!"; debugprint("[$count] -- writing domain file for $t"); foreach $host (@hosts) { print DOM "$host\n"; } close(DOM); } # end save domain file } } } } # create our domain maps foreach $key (keys(%master)) { @targets = (); @targets = @{$master{$key}}; if (scalar(@targets) != 0) { open(MAP,">>$key.dom") || exitclean("Could not create output file '$key.dom': $!"); foreach $host (@targets) { print MAP "$host\n"; } close(MAP) || debugprint("Could not close file '$key.dom': $!"); } }