#!/usr/bin/perl -w use strict; use File::Find; use Cwd 'abs_path'; BEGIN { ##Discover and use required modules automatically at compile time my $ABS_PATH = abs_path($0); find(\&wanted, $ABS_PATH); sub wanted { if ( $_ eq "eod_templates_V2.pm" or $_ eq "eod_functions_V2.pm"){unshift(@INC,$File::Find::dir);} } } use Data::Dumper; use Parallel::ForkManager; use Getopt::Long; Getopt::Long::Configure ("bundling"); use eod_templates_V2 qw(:ALL); use eod_functions_V2 qw(:ALL); my $path = Cwd::getcwd(); my $name = $0; $name =~ s/\.pl//; $name =~ s/\.\///; my $exit = 0; unless( ! @ARGV ){ $exit = Main(); }else{ print_help_and_exit($name); } exit($exit); sub process_command_line_args { #set default values for dynamic config settings my ($layout,$wait_for_child,$wait_for_exec,$prompt,$configf,$quiet,$outf,$debug,$batchsize,$proto,$tacacs,$verbose,$header,@maildst) = (0,120,3,1,"$name.cfg",1,"$name.csv",0,0,"none",0,0); GetOptions ( 'layout|l' => \$layout, 'file-based-auth|f' => sub { $prompt = 0;}, 'prompt-based-auth|p' => \$prompt, 'readfile|r=s' => \$configf, 'outfile|o=s' => \$outf, 'no-quiet|n' => sub { $quiet = 0; }, 'debug|d' => \$debug, 'Version|V' => \$header, 'max-connections|m=s' => \$batchsize, 'sendmail|s=s' => \@maildst, 'connection-proto|c=s' => \$proto, 'tacacs|t' => \$tacacs, 'verbose|v' => \$verbose, 'wait-for-childs|w=i' => \$wait_for_child, 'exec-time|e=i' => \$wait_for_exec, 'help|h' => sub { print_help_and_exit($name);} ) or print_help_and_exit($name); @maildst=split(/,/,join(',',@maildst)); #in case -s was invoked with a comma separated list instead of multiple times my $mailref = \@maildst; my @args = ($layout,$wait_for_child,$wait_for_exec,$name,$prompt,$configf,$quiet,$outf,$debug,$batchsize,$proto,$tacacs,$verbose,$header,$mailref,$path); return \@args; } sub Main { #get user defined dynamic config settings and perform various sanity checks my $argref = process_command_line_args(); my $batchsize = validate_command_line_args($argref); $argref->[9] = $batchsize; #all args check out now create and populate static hashes my (%STATIC,%REPORT); populate_static_hashes(\%STATIC,\%REPORT); #fill dynamic hash my %CONFIG; populate_config_hash(\%CONFIG,$argref); #set up global Output handling set_up_output_handle(\%CONFIG); #retrieve config settings from file my %DATA; get_config_from_file(\%DATA,\%CONFIG,\%STATIC); #print Dumper \%DATA; print Dumper \%CONFIG; print Dumper \%REPORT; warn("load configuration... done\nvalidate configuration... done\ninit all data structs... done\n"); #launch tacacs verification if it was requested my $result = 0; if ($CONFIG{tacacs} == 1){ warn("Commencing Tacacs verification process...\n"); $result = check_tacacs_functionality(\%CONFIG); unless($result == 0){ #username + password combination failed, abort execution if ( $CONFIG{mail_to} ){ #mail report was requested, send mail before aborting process_mail_request($result,\%CONFIG); } die("$0:ERROR tacacs functionality verification failed with EC: $result. Aborting script execution.\n"); } }else{ warn("Skipping Tacacs verification process due to user selection...\n"); } #prepare fork_manager operations warn("Configuring Fork manager...\n"); my $pm = configure_forkmanager_calls(\%CONFIG); #start processing devices warn("Distributing tasks to childs...\n"); for my $id (keys %DATA){ my $pid = $pm->start($id) and next; my $exitstate = process_device(\%CONFIG,\%DATA,\%STATIC,$id,$pm); #decide on protocol, call actual processing subs #exitstate 0 = OK # 1 = NOK => IP unreachable # 2 = NOK => wrong device password # 3 = NOK => no shell received $pm->finish($exitstate); } $pm->wait_all_children; #print Dumper \%DATA; print Dumper \%CONFIG; print Dumper \%REPORT; warn("Forkmanager completed all tasks, all childs terminated\n"); warn("Creating report from temp db...\n"); create_report_from_tempdb(\%REPORT,\%CONFIG); warn("Constructing and sending mail...\n"); process_mail_request(0,\%CONFIG,\%REPORT); unlink $CONFIG{tempdb} or warn("$0:WARNING Unable to delete $CONFIG{tempdb}. ERR:$?/$!\n"); warn("Main program completed.\nWill now close all open handles and exit...\n"); close(STDOUT); close(STDERR); return $exit; #will have to be set depending on outcome of actual script operations }