#!/usr/local/bin/perl # ################################################################################# # # Arp Data Processor ver 4.0 # # Goal : To process the data from arp watch program # letting you sort and search for specific data # # This is a perl script to process the data file produced by arpwatch # using an html interface. Adjust the first line to point to your perl. # # You can pretty up the background and buttons to your own # liking and I didn't add a "back" button as that tends to # be system specific. # # Author : B Johnston # # Copyright (c) 2000,2001,2002 B. Johnston # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ # # # # ver 1.1 : Fixed an error in the sh "if" test that gives problems # the first time you run when there is no $QUERY_STRING # defined. Also cleaned up the code and "looks". # # ver 1.2 : Found one minor error but the big error was the comments # inside the "cat <Arpview email "; ################################################################### # Open the arpwatch data file ################################################################### open(ARP_DATA, $arp_data); ################################################################### # Process the QUERY_STRING environment variable for the values # from the form. ################################################################### $QS = $ENV{"QUERY_STRING"}; $QS =~ s/\+//g; @para = split(/[&]/, $QS); for ($i = 1; $i <= $#para; $i++) { @tmp = split(/=/, $para[$i], 9999); $parameter{$tmp[1]} = $tmp[2]; } if ($parameter{'srch_str'} =~ /./) { $search_string = $parameter{'srch_str'}; } if ($parameter{'sort_order'} ne undef) { $sort_order = $parameter{'sort_order'}; } $downld = $parameter{'download'}; $date = localtime((stat($arp_data))[10]); ($wday,$month,$day,$hour,$year) = split(' ', $date); $file_date = sprintf('%s %s %s %s @ %s', $wday, $month, $day, $year, $hour); $count = 1; ################################################################### # Start the loop to process the data file, doing the sort based # on the $sort_order variable. Check out the ip number sort it # is a tricky little routine that does a logical not numeric sort. ################################################################### while () { ($edress,$ip_num,$jdate,$hostname) = split(' ', $_); $date = localtime($jdate); ($wday,$month,$day,$hour,$year) = split(' ', $date); $trans_date = sprintf('%s %s %s %s @ %s', $wday, $month, $day, $year, $hour); @tmp = split(/\./, $ip_num); $trans_ip = sprintf('%03d%03d%03d%03d', $tmp[1], $tmp[2], $tmp[3], $tmp[4]); $host{$count} = $hostname; $ip{$count} = $ip_num; $tip{$count} = $trans_ip; $date{$count} = $jdate; $tdate{$count} = $trans_date; $mac{$count} = $edress; $count++; } if ($sort_order eq 'hostname') { @sorted = sort by_hostname keys(%host); } elsif ($sort_order eq 'ip_num') { @sorted = sort by_ip keys(%tip); } elsif ($sort_order eq 'mac_num') { @sorted = sort by_mac keys(%mac); } else { @sorted = sort by_date keys(%date); $ip = $jdate; } ################################################################### # If you are downloading data fill the data array with comma delimited # data, if you are making a html table add the TR, TD needed to the # data as you load the array. ################################################################### ################################################################### # After processing the data file this generates the output, either # a html form or downloaded data. The "trick" to cause the download # is in declaring the TYPE as an octet-stream and the "Disposition" # allows me to put a filename on the downloaded data. Notice the use of # the perl format feature to build the html file doing it this way # makes it easier to change the form. # # The reason the FORM data was done with a print was needing to use # variables to load the VALUE fields. The perl format pads the fields # with spaces which are translated to "+" when passed through the FORM # causing problems. I found it easier to use the print command then # adding code to strip the "+", personal preference. ################################################################### if ($downld eq 'download') { if ($parameter{'format'} eq 'excel') { print("Content-TYPE: application/octet-stream"); print("Content-Disposition: attachment; filename=\"".$downld_file."csv\"\n"); print("Name,IP,MAC,Julian,Time"); foreach $i (@sorted) { $data = sprintf("%s,%s,%s,%s,%s",$host{$i},$ip{$i},$mac{$i},$date{$i},$tdate{$i}); $data =~ s///; $data =~ s/<.*>//; if ($data =~ /$search_string/) { print($data); } } } else { print("Content-TYPE: application/octet-stream"); print("Content-Disposition: attachment; filename=\"".$downld_file."txt\"\n"); print("Arpview Data - last updated " . $file_date . "\n"); print("File : " . $downld_file . "txt (Duplicates indicated by *)"); print("+================+=================+===================+=============================+"); printf("|%15s |%16s |%18s |%28s |\n", "Hostname", "IP Address", "Mac Address", "Date"); print("+----------------+-----------------+-------------------+-----------------------------+"); foreach $i (@sorted) { $host{$i} =~ s//*/; $host{$i} =~ s/<.*>//; $ip{$i} =~ s//*/; $ip{$i} =~ s/<.*>//; $mac{$i} =~ s//*/; $mac{$i} =~ s/<.*>//; $tdate{$i} =~ s//*/; $tdate{$i} =~ s/<.*>//; $data = sprintf("|%15s |%16s |%18s |%28s |",$host{$i},$ip{$i},$mac{$i},$tdate{$i}); if ($data =~ /$search_string/) { print($data); } } print("+================+=================+===================+=============================+"); } } else { $~ = "HTML1"; write; print("
\n"); $~ = "HTML2"; write; print("\n", "\n", "\n", "\n", "\n", "Format : \n", "Excel (csv)\n", "Report (txt)\n", "
\n"); if ($duplicate == 1) { print("Duplicate " . $sort_order . " shown in RED\n", "
\n"); } $~ = "TABLEHEAD"; write; foreach $i (@sorted) { $data = ('' . $host{$i} . '' . $ip{$i} . '' . $mac{$i} . '' . $date{$i} . '' . $tdate{$i} . ''); if ($data =~ /$search_string/) { print($data); } } $~ = HTMLEND; write; } ################################################################### # Formats ################################################################### # These are the formats for the write commands that hold the html # code. You can customize the FORMS and TABLE as you see fit. ################################################################### format HTML1 = Content-TYPE: text/html ArpView data

Processed Arp Data

last updated : @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

$file_date



. ################################################################### format HTML2 =

Search String : (This search uses "grep -i" on the @<<<<<<<<<<<<<<<<<<<<<<<<<<< file) $arp_data

Sort Data by : (Currently sorted by @<<<<<<<< ) $sort_order

: Hostname : IP # : MAC # : Date

. ################################################################### format TABLEHEAD =

. ################################################################### format HTMLEND =
NameIPMACAbs TimeHuman Time
@* $signature . ################################################################### # Subroutines ################################################################### sub by_hostname { $return = $host{$a} cmp $host{$b}; if (($host{$a} cmp $host{$b}) == 0) { $host{$a} = " " . $host{$a} . ""; $host{$b} = " " . $host{$b} . ""; $duplicate = 1; } $return; } sub by_ip { $return = $tip{$a} <=> $tip{$b}; if (($tip{$a} <=> $tip{$b}) == 0) { $ip{$a} = " " . $ip{$a} . ""; $ip{$b} = " " . $ip{$b} . ""; $duplicate = 1; } $return; } sub by_mac { $return = $mac{$a} cmp $mac{$b}; if (($mac{$a} cmp $mac{$b}) == 0) { $mac{$a} = " " . $mac{$a} . ""; $mac{$b} = " " . $mac{$b} . ""; $duplicate = 1; } $return; } sub by_date { $return = $date{$a} <=> $date{$b}; if(($date{$a} <=> $date{$b}) == 0) { $tdate{$a} = " " . $tdate{$a} . ""; $tdate{$b} = " " . $tdate{$b} . ""; } $return; }