#! /usr/bin/perl # # Purpose: # FlowViewer_Main.cgi permits a Web user to analyze Net Flow data stored # in flow tools format and create an HTML report. # # Description: # The script responds to an HTML form from the user in order to collect # parameters that will control the analysis (e.g., router, time-period, ip # addresses etc.) Upon receipt of the form input the script creates a flow tools # filter file which controls the selection of the data via the invocation of # additional flow tools utilities. An HTML report is then generated. # # Input arguments (received from the form): # Name Description # ----------------------------------------------------------------------- # device_name An identifying name of the device (e.g. router1) # flow_select Identifies which flows to include wrt time period # start_date Start date of analysis period # start_time Start time of analysis period # end_date End date of analysis period # end_time End time of analysis period # source_addresses Constrain flows examined to these source IP addresses # source_ports Constrain flows examined to these source ports # source_ifs Constrain flows examined to these input interfaces # source_ases Constrain flows examined to these source ASes # dest_addresses Constrain flows examined to these dest. IP addresses # dest_ports Constrain flows examined to these dest. ports # dest_ifs Constrain flows examined to these output interfaces # dest_ases Constrain flows examined to these dest. ASes # tos_fields Constrain flows examined by specified TOS field values # tcp_flags Constrain flows examined by specified TCP flag values # protocols Constrain flows examined to these protocols # print_report Select from these various report options # stat_report Select from these various statistics options # cutoff_lines Number of report lines to print out # cutoff_octets Minimum number of octets for inclusion in report # sort_field Which report column to sort lines upon # resolve_addresses Whether or not to resolve IP addresses # # Notes: # 1. It is a good idea to retain the host_names GDBM file (names), even if it # gets large, since it is up to 1000 times faster than using 'dig'. # # Modification history: # Author Date Vers. Description # ----------------------------------------------------------------------- # J. Loiacono 07/04/2005 1.0 Original version. # J. Loiacono 01/01/2006 2.0 FlowGrapher, new functions, speed # J. Loiacono 01/16/2006 2.1 Fixed compute of concatenation date # J. Loiacono 01/26/2006 2.2 New flow_select option for inclusion # J. Loiacono 07/04/2006 3.0 Renamed for re-organization # Single script for GDBM/NDBM (thanks Ed Ravin) # J. Loiacono 12/25/2006 3.1 [No Change to this module] # J. Loiacono 02/14/2007 3.2 [No Change to this module] # #$Author$ #$Date$ #$Header$ # ########################################################################### # # BEGIN EXECUTABLE STATEMENTS # use FlowViewer_Configuration; use FlowViewer_Utilities; if ($debug_viewer eq "Y") { open (DEBUG,">$work_directory/DEBUG_VIEWER"); } if ($debug_viewer eq "Y") { print DEBUG "In FlowViewer_Main.cgi\n"; } # Tie in the appropriate 'names' files which saves IP address resolved names if (eval 'local $SIG{"__DIE__"}= sub { }; use GDBM_File; tie %host_names, "GDBM_File", "$names_directory/names", GDBM_WRCREAT, 0666;' ) { print DEBUG "Using GDBM\n"; }; if (eval 'local $SIG{"__DIE__"}= sub { }; use NDBM_File; use Fcntl; tie %host_names, "GDBM_File", "$names_directory/names", GDBM_WRCREAT, 0666;' ) { print DEBUG "Using NDBM\n"; }; # Tie in the appropriate 'as_names' file which saves resolved AS names if (eval 'local $SIG{"__DIE__"}= sub { }; use GDBM_File; tie %as_names, "GDBM_File", "$names_directory/as_names", GDBM_WRCREAT, 0666;' ) { print DEBUG "Using GDBM\n"; }; if (eval 'local $SIG{"__DIE__"}= sub { }; use NDBM_File; use Fcntl; tie %as_names, "GDBM_File", "$names_directory/as_names", GDBM_WRCREAT, 0666;' ) { print DEBUG "Using NDBM\n"; }; # Retrieve the form inputs read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; $FORM{$name} = $value; } # Clean up input $FORM{source_address} =~ s/\s+//g; $FORM{source_address} =~ s/,/, /g; $FORM{source_port} =~ s/\s+//g; $FORM{source_port} =~ s/,/, /g; $FORM{source_if} =~ s/\s+//g; $FORM{source_if} =~ s/,/, /g; $FORM{source_as} =~ s/\s+//g; $FORM{source_as} =~ s/,/, /g; $FORM{dest_address} =~ s/\s+//g; $FORM{dest_address} =~ s/,/, /g; $FORM{dest_port} =~ s/\s+//g; $FORM{dest_port} =~ s/,/, /g; $FORM{dest_if} =~ s/\s+//g; $FORM{dest_if} =~ s/,/, /g; $FORM{dest_as} =~ s/\s+//g; $FORM{dest_as} =~ s/,/, /g; $FORM{protocols} =~ s/\s+//g; $FORM{protocols} =~ s/,/, /g; $FORM{tos_fields} =~ s/\s+//g; $FORM{tos_fields} =~ s/,/, /g; $FORM{tcp_flags} =~ s/\s+//g; $FORM{tcp_flags} =~ s/,/, /g; # Parameters for generating a FlowViewer report $device_name = $FORM{'device_name'}; $flow_select = $FORM{'flow_select'}; $start_date = $FORM{'start_date'}; $start_time = $FORM{'start_time'}; $end_date = $FORM{'end_date'}; $end_time = $FORM{'end_time'}; $source_addresses = $FORM{'source_address'}; $source_ports = $FORM{'source_port'}; $source_ifs = $FORM{'source_if'}; $source_ases = $FORM{'source_as'}; $dest_addresses = $FORM{'dest_address'}; $dest_ports = $FORM{'dest_port'}; $dest_ifs = $FORM{'dest_if'}; $dest_ases = $FORM{'dest_as'}; $protocols = $FORM{'protocols'}; $tcp_flags = $FORM{'tcp_flags'}; $tos_fields = $FORM{'tos_fields'}; $print_report = $FORM{'print_report'}; $stat_report = $FORM{'stat_report'}; $cutoff_lines = $FORM{'cutoff_lines'}; $cutoff_octets = $FORM{'cutoff_octets'}; $sort_field = $FORM{'sort_field'}; $resolve_addresses = $FORM{'resolve_addresses'}; # Build call string to provide filter parameters to either FlowGrapher or FlowTracker $call_string = "device_name=$device_name&"; $call_string .= "start_date=$start_date&"; $call_string .= "start_time=$start_time&"; $call_string .= "end_date=$end_date&"; $call_string .= "end_time=$end_time&"; $call_string .= "source_addresses=$source_addresses&"; $call_string .= "source_ports=$source_ports&"; $call_string .= "source_ifs=$source_ifs&"; $call_string .= "source_ases=$source_ases&"; $call_string .= "dest_addresses=$dest_addresses&"; $call_string .= "dest_ports=$dest_ports&"; $call_string .= "dest_ifs=$dest_ifs&"; $call_string .= "dest_ases=$dest_ases&"; $call_string .= "protocols=$protocols&"; $call_string .= "tcp_flags=$tcp_flags&"; $call_string .= "tos_fields=$tos_fields&"; $call_string =~ s/\s+//g; $save_file = "$device_name"; # Start web page output in case of errors print "Content-type:text/html\n\n"; print ""; print "
"; # Check dates and times for input errors ($mn,$da,$yr) = split(/\//,$start_date); if ( $mn=~/\D/ || $da=~/\D/ || $yr=~/\D/ ) { &print_error("Bad date format: $start_date"); }; if ( $mn<1 || $mn>12 || $da<1 || $da>31 || $yr<1990 || $yr>2100 ) { &print_error("Bad date format: $start_date"); } if (length($mn) < 2) { $mn = "0" . $mn; } if (length($da) < 2) { $da = "0" . $da; } $start_ymd = $yr . $mn . $da; ($hr,$mi,$sc) = split(/:/,$start_time); if ( $hr=~/\D/ || $mi=~/\D/ || $sc=~/\D/ ) { &print_error("Bad time format: $start_time"); }; if (length($hr)>2 || $hr>23 || length($mi)>2 || $mi>59 || length($sc)>2 || $sc>59 ) { &print_error("Bad time format: $start_time"); } ($mn,$da,$yr) = split(/\//,$end_date); if ( $mn=~/\D/ || $da=~/\D/ || $yr=~/\D/ ) { &print_error("Bad date format: $end_date"); }; if ( $mn<1 || $mn>12 || $da<1 || $da>31 || $yr<1990 || $yr>2100 ) { &print_error("Bad date format: $end_date"); } if (length($mn) < 2) { $mn = "0" . $mn; } if (length($da) < 2) { $da = "0" . $da; } $end_ymd = $yr . $mn . $da; ($hr,$mi,$sc) = split(/:/,$end_time); if ( $hr=~/\D/ || $mi=~/\D/ || $sc=~/\D/ ) { &print_error("Bad time format: $end_time"); }; if (length($hr)>2 || $hr>23 || length($mi)>2 || $mi>59 || length($sc)>2 || $sc>59 ) { &print_error("Bad time format: $end_time"); } if (($stat_report == 0) && ($print_report == 0)) { print "
Must specify a report.

Use the \"back\" key to save inputs
"; exit; } if (($stat_report ne "0") && ($print_report ne "0")) { print "
Two reports selected. Reset one of them.

Use the \"back\" key to save inputs
"; exit; } # Retrieve current time to use as a file suffix to permit more than one user to generate reports ($sec,$min,$hr,$date,$mnth,$yr,$day,$yr_date,$DST) = localtime(time); $mnth++; $yr += 1900; if ((0 < $mnth) && ($mnth < 10)) { $mnth = "0" . $mnth; } if ((0 < $date) && ($date < 10)) { $date = "0" . $date; } if ((0 <= $hr) && ($hr < 10)) { $hr = "0" . $hr; } if ((0 <= $min) && ($min < 10)) { $min = "0" . $min; } if ((0 <= $sec) && ($sec < 10)) { $sec = "0" . $sec; } $prefix = $yr . $mnth . $date ."_". $hr . $min . $sec; $suffix = $hr . $min . $sec; # Determine the flow files concatenation start and end time $start_epoch = date_to_epoch($start_date,$start_time,"LOCAL"); $end_epoch = date_to_epoch($end_date,$end_time,"LOCAL"); $report_length = $end_epoch - $start_epoch; if ($report_length <= 0) { &print_error("End time ($end_date $end_time) earlier than Start time ($start_date $start_time)"); } $start_flows = &flow_date_time($start_epoch,"LOCAL"); $end_flows = &flow_date_time($end_epoch,"LOCAL"); $cat_start_epoch = $start_epoch - $flow_file_length - 1; $cat_end_epoch = $end_epoch + $flow_capture_interval + 1; $cat_start = epoch_to_date($cat_start_epoch,"LOCAL"); $cat_end = epoch_to_date($cat_end_epoch,"LOCAL"); $concatenate_parameters = "-t \"$cat_start\" -T \"$cat_end\" "; if (($start_ymd ne $end_ymd) && ($end_epoch > $start_epoch)) { for ($i=0;$i<$maximum_days;$i++) { if (($cat_start_epoch + $i*86400) > $cat_end_epoch + 86400) { last; } ($sec,$min,$hr,$cat_date,$cat_mnth,$cat_yr,$day,$yr_date,$DST) = localtime($cat_start_epoch + $i*86400); $cat_mnth++; $cat_yr += 1900; if ((0 < $cat_mnth) && ($cat_mnth < 10)) { $cat_mnth = "0" . $cat_mnth; } if ((0 < $cat_date) && ($cat_date < 10)) { $cat_date = "0" . $cat_date; } $cat_directory = "$flow_data_directory/$device_name"; if ($N == -3) { $cat_directory .= "/$cat_yr/$cat_yr\-$cat_mnth/$cat_yr\-$cat_mnth\-$cat_date"; } if ($N == -2) { $cat_directory .= "/$cat_yr\-$cat_mnth/$cat_yr\-$cat_mnth\-$cat_date"; } if ($N == -1) { $cat_directory .= "/$cat_yr\-$cat_mnth\-$cat_date"; } if ($N == 1) { $cat_directory .= "/$cat_yr"; } if ($N == 2) { $cat_directory .= "/$cat_yr/$cat_yr\-$cat_mnth"; } if ($N == 3) { $cat_directory .= "/$cat_yr/$cat_yr\-$cat_mnth/$cat_yr\-$cat_mnth\-$cat_date"; } $concatenate_parameters .= "$cat_directory "; if ($N == 0) { last; } } } elsif ($start_ymd eq $end_ymd) { ($sec,$min,$hr,$cat_date,$cat_mnth,$cat_yr,$day,$yr_date,$DST) = localtime($cat_end_epoch); $cat_mnth++; $cat_yr += 1900; if ((0 < $cat_mnth) && ($cat_mnth < 10)) { $cat_mnth = "0" . $cat_mnth; } if ((0 < $cat_date) && ($cat_date < 10)) { $cat_date = "0" . $cat_date; } $cat_directory = "$flow_data_directory/$device_name"; if ($N == -3) { $cat_directory .= "/$cat_yr/$cat_yr\-$cat_mnth/$cat_yr\-$cat_mnth\-$cat_date"; } if ($N == -2) { $cat_directory .= "/$cat_yr\-$cat_mnth/$cat_yr\-$cat_mnth\-$cat_date"; } if ($N == -1) { $cat_directory .= "/$cat_yr\-$cat_mnth\-$cat_date"; } if ($N == 1) { $cat_directory .= "/$cat_yr"; } if ($N == 2) { $cat_directory .= "/$cat_yr/$cat_yr\-$cat_mnth"; } if ($N == 3) { $cat_directory .= "/$cat_yr/$cat_yr\-$cat_mnth/$cat_yr\-$cat_mnth\-$cat_date"; } $concatenate_parameters .= "$cat_directory "; } else { &print_error("Start day ($start_date) is past End day ($end_date)"); } # Create the filter to match the input specifications $filter_file = "$work_directory/FlowViewer_filter_$suffix"; create_filter_file(%FORM,$filter_file); # Set up the command to concatenate the files $flowcat_command = "$flow_bin_directory/flow-cat" . " $concatenate_parameters"; # Set up the command to filter the concatenated file $flownfilter_command = "$flow_bin_directory/flow-nfilter -f $work_directory/FlowViewer_filter_$suffix -FFlow_Filter"; # Set up the flow-stat command if requested if ($stat_report ne "0") { $sort_field--; if ($stat_report eq "99") { $flowstat_command = "$flow_bin_directory/flow-stat -S$sort_field >$work_directory/FlowViewer_output_$suffix"; } else { $flowstat_command = "$flow_bin_directory/flow-stat -f$stat_report -S$sort_field >$work_directory/FlowViewer_output_$suffix"; } $flow_run = "$flowcat_command | $flownfilter_command | $flowstat_command"; } # Set up the flow-print command if requested if ($print_report ne "0") { $flowprint_command = "$flow_bin_directory/flow-print -f$print_report >$work_directory/FlowViewer_output_$suffix"; $flow_run = "$flowcat_command | $flownfilter_command | $flowprint_command"; } # Execute the piped flow-tools command if ($debug_viewer eq "Y") { print DEBUG "\n$flow_run\n\n"; } system ($flow_run); $sort_field++; if ($print_report ne "0") { $sort_field = "n/a"; } if ($stat_report == 99) { $report_title = "Summary"; } if ($stat_report == 5) { $report_title = "UDP/TCP Destination Port"; } if ($stat_report == 6) { $report_title = "UDP/TCP Source Port"; } if ($stat_report == 7) { $report_title = "UDP/TCP Port"; } if ($stat_report == 8) { $report_title = "Destination IP"; } if ($stat_report == 9) { $report_title = "Source IP"; } if ($stat_report == 10) { $report_title = "Source/Destination IP"; } if ($stat_report == 11) { $report_title = "Source or Destination IP"; } if ($stat_report == 12) { $report_title = "IP Protocol"; } if ($stat_report == 17) { $report_title = "Input Interface"; } if ($stat_report == 18) { $report_title = "Output Interface"; } if ($stat_report == 23) { $report_title = "Input/Output Interface"; } if ($stat_report == 19) { $report_title = "Source AS"; } if ($stat_report == 20) { $report_title = "Destination AS"; } if ($stat_report == 21) { $report_title = "Source/Destination AS"; } if ($stat_report == 22) { $report_title = "IP ToS"; } if ($stat_report == 24) { $report_title = "Source Prefix"; } if ($stat_report == 25) { $report_title = "Destination Prefix"; } if ($stat_report == 26) { $report_title = "Source/Destination Prefix"; } $resolve_columns = 0; if (($resolve_addresses eq "Y") && ($stat_report == 8)) { $resolve_columns = 1; } if (($resolve_addresses eq "Y") && ($stat_report == 9)) { $resolve_columns = 1; } if (($resolve_addresses eq "Y") && ($stat_report == 10)) { $resolve_columns = 2; } if (($resolve_addresses eq "Y") && ($stat_report == 11)) { $resolve_columns = 1; } if (($resolve_addresses eq "Y") && ($stat_report == 19)) { $resolve_columns = 3; } if ($print_report == 1) { $report_title = "Flow Times"; } if ($print_report == 4) { $report_title = "AS Numbers"; } if ($print_report == 5) { $report_title = "132 Columns"; } if ($print_report == 9) { $report_title = "1 Line with Tags"; } if ($print_report == 10) { $report_title = "AS Aggregation"; } if ($print_report == 11) { $report_title = "Protocol Port Aggregation"; } if ($print_report == 12) { $report_title = "Source Prefix Aggregation"; } if ($print_report == 13) { $report_title = "Destination Prefix Aggregation"; } if ($print_report == 14) { $report_title = "Prefix Aggregation"; } if ($print_report == 24) { $report_title = "Full (Catalyst)"; } # Output the FlowViewer report print "FlowViewer $version Report Results"; print "

\n"; print ""; print ""; print ""; print HTML ""; print HTML ""; print HTML "
"; print "

"; # Begin a temporary copy of the report page in case user wishes to save $save_file =~ s/\//_/g; $save_filename = $prefix ."_". $save_file . ".html"; open (HTML,">$work_directory/$save_filename"); print HTML "FlowViewer Report Results (Saved)"; print HTML ""; print HTML "

\n"; print HTML ""; print HTML ""; print HTML ""; print ""; print ""; # Output report input filtering criteria print ""; print ""; print ""; print ""; print ""; print ""; print ""; print ""; print HTML ""; print HTML ""; print HTML ""; print HTML ""; print HTML ""; print HTML ""; print HTML ""; print ""; print ""; print "
"; print HTML ""; # Output button saved report print "
"; print "
"; print "
\n"; 
printf "      Report: %-28s                     Sort Field: %-4s\n", $report_title, $sort_field;
printf "  Start Time: %-28s                       End Time: %-28s\n", $start_flows, $end_flows;

print_formatted_parameters(%FORM, $html_file);

printf "Lines Cutoff: %-28s                  Octets Cutoff: %-11s\n", $cutoff_lines, $cutoff_octets;
printf "  Include if: %-31s   \n", $flow_select_manner;
print "
"; print "
";

# Continue with temporary copy for saving later 

print HTML "
"; print HTML "
";
printf HTML "      Report: %-28s                     Sort Field: %-4s\n", $report_title, $sort_field;
printf HTML "  Start Time: %-28s                       End Time: %-28s\n", $start_flows, $end_flows;

$html_file = "$work_directory/$save_filename";
print_formatted_parameters(%FORM, $html_file);

printf HTML "Lines Cutoff: %-28s                  Octets Cutoff: %-11s\n", $cutoff_lines, $cutoff_octets;
printf HTML "  Include if: %-31s   \n", $flow_select_manner;
print HTML "
"; print HTML "
";
print HTML "\n";

if (($print_report ne 0) || ($stat_report eq "99")) {
	print "#\n#\n";
	print HTML "#\n#\n";
}

# Parse through the intermediate, flow tools generated, 'FlowViewer_output' file

open (OUTPUT,"<$work_directory/FlowViewer_output_$suffix");
while () {
	if (($stat_report ne "0") && (substr($_,0,6) eq "# Args")) { 
		$start_printing = 1;
		next; }
	if ($print_report ne "0") { 
		$start_printing = 1; }
	else {
		if (!$start_printing) { next; }
	}
	$line_count++;

	if (substr($_,0,1) eq "#") {
		chop;
		if ((substr($_,0,4) eq "# IP") && ($resolve_columns == 1)) {
			$left_half = "# Host                        ";
			$right_half = substr($_,17,132);
			$line = $left_half . $right_half;
                        if ($stat_report == 10) {
                                $line = $line ."          Avg. rate(bps)";
                        }
			print       "$line\n";
			print HTML "$line\n"; }
		elsif ((substr($_,0,5) eq "# src") && ($resolve_columns == 2)) {
			$left_half = "# Source                       Destination                   ";
			$right_half = substr($_,34,132);
			$line = $left_half . $right_half;
                        if ($stat_report == 10) {
                                $line = $line ."          Avg. rate(bps)";
                        }
			print       "$line\n";
			print HTML "$line\n"; }
                elsif ((substr($_,0,5) eq "# src") && ($resolve_columns == 3)) { 
                        $left_half = "# AS name                     ";       
                        $right_half = substr($_,12,132); 
                        $line = $left_half . $right_half; 
                        print       "$line\n"; 
                        print HTML "$line\n"; }
		else {
                        if (($stat_report == 10) && (substr($_,0,5) eq "# src")){
                                $line = $_ ."          Avg. rate(bps)";
                                print       "$line\n";
                                print HTML "$line\n"; }
                        else  {
                                print       "$_\n";
                                print HTML "$_\n";
                        }
                        if ($stat_report == 10) {
                                $line = $line ."          Avg. rate(bps)";
                        }
		}
		next;
	}

	if (($stat_report == 10) || ($stat_report == 21) || ($stat_report == 23) || ($stat_report == 26)) { 
		($x,$y,$z,$octets) = split(/\s+/,$_); }
	else {
		($x,$y,$octets)    = split(/\s+/,$_);
	}

	if (($stat_report != 0) && ($octets < $cutoff_octets)) { last; }

	if ($resolve_columns == 1) {
		chop;
		($s_address,$d_address) = split(/\s+/,$_);
		$line = substr($_,17,132);
		$s_name = dig($s_address);
		printf       "%-30s",$s_name;
		printf HTML "%-30s",$s_name;
                if ($stat_report eq 10) {
                        $flow_rate = int($octets*8/$report_length);
                        $line = $line ."  ". $flow_rate;
                }
		print       "$line\n";
		print HTML "$line\n"; }
	elsif ($resolve_columns == 2) {
		chop;
		($s_address,$d_address) = split(/\s+/,$_);
		$line = substr($_,34,132);
		$s_name = dig($s_address);
		$d_name = dig($d_address);
		printf       "%-30s %-30s",$s_name,$d_name;
		printf HTML "%-30s %-30s",$s_name,$d_name;
                if ($stat_report eq 10) {
                        $flow_rate = int($octets*8/$report_length);
                        $line = $line ."  ". $flow_rate;
                }
		print       "$line\n";
		print HTML "$line\n";
	}
        elsif ($resolve_columns == 3) {  
                chop;    
                ($s_address,$d_address) = split(/\s+/,$_); 
                $line = substr($_,12,132); 
                $s_name = dig_as($s_address); 
                printf       "%-30s",$s_name; 
                printf HTML "%-30s",$s_name; 
                print       "$line\n"; 
                print HTML "$line\n"; 
        }
	else {
		chop;
                if ($stat_report eq "10") {
                        $flow_rate = int($octets*8/$report_length);
                        $line = $_ ."  ". $flow_rate;
                        print "$line\n";
                        print HTML "$line\n"; }
		else {
			print       "$_\n";
			print HTML "$_\n";
		}
	}

	if (($line_count-3) > $cutoff_lines) { last; }
}
print "
"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print HTML "
"; print HTML "\n"; print HTML "\n"; print HTML "\n"; print HTML "\n"; print HTML "\n"; print HTML "\n"; # Remove intermediate files $rm_command = "rm $work_directory/FlowViewer_filter_$suffix"; if ($debug_files ne "Y") { system($rm_command); } $rm_command = "rm $work_directory/FlowViewer_output_$suffix"; if ($debug_files ne "Y") { system($rm_command); } # Subroutines sub print_error { my ($error_text) = @_; print "FlowViewer $version Error Report"; print "
\n"; print ""; print "FlowViewer Report Error"; print "

$error_text
"; print "
Use the \"back\" key to modify

"; print "
\n"; exit; } sub dig { my ($host_address) = @_; $host_name = $host_address; if (defined($host_names{$host_address})) { $host_name = $host_names{$host_address}; } else { open(DIG,"$dig $host_address 2>&1|"); $answer_record = 0; while () { chop; if (/ANSWER SECTION/) { $answer_record = 1; next; } if ($answer_record) { ($in_addr,$rec_timeout,$rec_direction,$rec_type,$host_name) = split(/\s+/,$_); $last_period = rindex($host_name,"\."); $host_name = substr($host_name,0,$last_period); $length_name = length($host_name); if ($length_name > 30) { $left_start = $length_name - 30; $host_name = substr($host_name,$left_start,30); } if (/CNAME/) { $host_name = $host_address; } last; } } if (length($host_name) < 1) { $host_name = $host_address; } $host_names{$host_address} = $host_name; } return $host_name; } sub dig_as { my ($host_address) = @_; $as_name = $host_address; if (defined($as_names{$host_address})) { $as_name = $as_names{$host_address}; } else { open(DIG_AS,"whois -h whois.cymru.com as$host_address 2>&1|"); $answer_record = 0; while () { chop; if (/AS Name/) { $answer_record = 1; next; } if ($answer_record) { ($as_number,$as_name) = split(/\|/,$_); $length_name = length($as_name); if ($length_name > 30) { $left_start = $length_name - 28; $as_name = substr($as_name,$left_start,28); } } } $as_names{$host_address} = $as_name; } return $as_name; }