#!/usr/bin/perl

#
#  Search IPaudit data files for ip address
#

$PAGE_TITLE="Search IPAUDIT data files for ipaddress";
$MAINT_NAME="J. Rifkin";
$MAINT_EMAIL="jon.rifkin\@uconn.edu";
$UPDATED_DATE="Apr 4, 2000";
$ZGREP="/usr/bin/zgrep";
$DATA_DIR="/home/ipaudit/data/30min";
$MIN_SORT_FIELD=1;
$MAX_SORT_FIELD=13;
$DEFAULT_SORT_FIELD=0;

$PROT_TCP=6;
$PROT_UDP=17;

@color=(
"#6c6c00",
"#6c6c00",

"#8d3515",

"#242490",
"#242490",

"#025a7b",
"#025a7b",

"#860948",
"#860948",

"#098648",
"#098648",

"#5a027b",
"#5a027b",

"#358d15",
"#358d15"
);

@format=(
"%15s", 
"%15s", 
"%2d", 
"%s", 
"%s",  
"%9d", 
"%9d", 
"%5d", 
"%5d", 
"%s", 
"%s", 
"%d", 
"%d"
);

# Column key
@colkey = (
"Local IP", 
"Remote IP", 
"Protocol (1=icmp, 6=tcp, 17=udp)", 
"Local Port", 
"Remote Port", 
"Incoming (bytes)", 
"Outgoing (bytes)", 
"Incoming (packets)", 
"Outgoing (packets)", 
"First Packet time", 
"Last Packet time", 
"First Packet source", 
"Last Packet source (1=Local,2=Remote)"
);

#  Get directory of this script: relative to native file system root, and http root
($scriptdir) = ($ENV{SCRIPT_FILENAME}=~/^(.*)\/([^\/]+)$/);
($cgidir) = ($ENV{SCRIPT_NAME}=~/^(.*)\/([^\/]+)$/);

#  Look up known ports, store in %port as 23u 1024t etc
if (open F, "$scriptdir/port.lst") {
while (<F>) {
next if /^\s*#/;
@F=split(/\s*[\|]\s*/);
$F[0]=~s/^\s+//;
$port{$F[0]} = 1;
}
}
close F;

# Parse arguments
for (split(/&/,$ENV{QUERY_STRING})) {
	s/%3A/:/g;
	($key,$val) = split /=/;
	$arg{$key} = $val;
}

# Default arguments
#  sort value can be either + or -
$arg{sort} = $DEFAULT_SORT_FIELD  unless 
	defined $arg{sort} && 
	($arg{sort} >= $MIN_SORT_FIELD && $arg{sort} <= $MAX_SORT_FIELD ||  
	$arg{sort} <= -$MIN_SORT_FIELD && $arg{sort} >= -$MAX_SORT_FIELD);

#
#  Draw form at page top
#
$PAGE_TITLE="Search IPAUDIT data files for ipaddress";
print<<"EOM";
Content-type: text/html

<html><head><title>$PAGE_TITLE</title></head>
<body bgcolor=#dddddd link=$color[4] vlink=$color[4]>
<h2 align=center>$PAGE_TITLE</h2><p><hr noshade><p>
<form action="/cgi-bin/ipaudit/SearchIpauditData" method=get>
<table>
<tr>
<td>Enter:</td>
<th>Date Range</th>
<td><input type=text NAME=date value="$arg{date}" size=16></td>
<td>&nbsp;&nbsp;<i>example, 2000-01-23-21:30</i></td>
</tr>
<tr>
<td></td>
<th>IP address</th>
<td><input type=text NAME=ip value="$arg{ip}" size=16></td>
<td>&nbsp;&nbsp;<i>example, 137.99.23.5</i></td>
</tr>
<tr>
<td></td>
<th>Sort field</th>
<td><input type=text NAME=sort value="$arg{sort}" size=16></td>
<td>&nbsp;&nbsp;<i>$MIN_SORT_FIELD through $MAX_SORT_FIELD, negative for reverse sort</i></td>
</tr>
<tr>
<td></td>
<th></th>
<td><input type=submit value="submit" size=16></td>
<td></td>
</tr>
</table>
</form>
<hr noshade>
<tt>
<b>
<p align="left">Column Key</p>
</b>
<font size=-1>
EOM

#  Print column key
%skip = ( 2=>1, 3=>1, 5=>1, 7=>1, 9=>1, 11=>1 );
for $i ( 0 .. $#colkey) {
	printf "&nbsp; &nbsp; <font color=\"%s\"><b>%d</b>-%s</font>", $color[$i], $i+1, $colkey[$i];
	print "<br>\n" if  $skip{$i+1};
}
print "</font></tt>\n";


goto FINISH_PAGE unless defined($ENV{QUERY_STRING}) && $ENV{QUERY_STRING} ne "";

print "<p><hr noshade><p>\n";


#
#  One or more arguments (ignore extra)
#

# Parse arguments
for (split(/&/,$ENV{QUERY_STRING})) {
	s/%3A/:/g;
	($key,$val) = split /=/;
	$arg{$key} = $val;
}

# Format date and ip
#
#$date = sprintf "%04d-%02d-%02d-%02d:%02d", 
#  ($arg{date}=~/(\d+)-(\d+)-(\d+)-(\d+):(\d+)/);
$date = $arg{date};
$ip   = sprintf "%03d.%03d.%03d.%03d",      ($arg{ip}  =~/(\d+).(\d+).(\d+).(\d+)/);
	

#  print list heading
print<<"EOM";
<font size=+1><tt>
Date: <b>$date</b><br>
IP&nbsp; : <b>$ip</b><br>
</tt></font>
<br><br>
EOM

$COMMAND="$ZGREP $ip $DATA_DIR/$date* | ";
#  Grep files for strings
if (open (F, $COMMAND)) {
	if ($arg{sort}<0) {
		$sortfield = 1 - $arg{sort};
	} elsif ($arg{sort}>0)  {
		$sortfield = $arg{sort} - 1;
	} else {
		$sortfield = 0;
	}

	print "<tt><b><font size=-1><pre>\n";

	#  Sort before printing
	if ($sortfield>0) {
		$i = 0;
		while (<F>) { 
			@F = split;
			$index[$i] = $i;
			$lines[$i] = $_;
			$key  [$i] = $F[$sortfield] if $sortfield>0;
			$i++;
		}

		#  Sort by key
		for $i (sort {fcmp($arg{sort}, $key[$index[$a]], $key[$index[$b]])} @index) {
			@F = split(/\s+/, $lines[$i]);
			($F[0]) = ($F[0]=~/:([^:]+)$/);
			$f=0;
			for (@F) {
				printf "  <font color=$color[$f]>$format[$f]", $_;
				$f++;
			}
			print "</font>\n";
		}

	#  Do not sort before printing
	} else {
		while (<F>) {
			chomp;
			@F = split;
			($F[0]) = ($F[0]=~/:([^:]+)$/) if $F[0]=~/:/;

			#  Check for tcp ports
			$p3    = $F[3];
			$p4    = $F[4];
			$pform3 = sprintf "%5d", $F[3];
			$pform4 = sprintf "%5d", $F[4];
			$F[3]   = $pform3;
			$F[4]   = $pform4;
			if ($F[2] == $PROT_TCP) {
				if  (defined($port{"${p3}t"})) {
					$F[3] = &porturl("${p3}t") . "$pform3</a>";
				}
				if  (defined($port{"${p4}t"})) {
					$F[4] = &porturl("${p4}t") . "$pform4</a>";
				}
			#  Check for udp ports
			} elsif ($F[2] == $PROT_UDP) {
				if  (defined($port{"${p3}u"})) {
					$F[3] = &porturl("${p3}u") . "$pform3</a>";
				}
				if  (defined($port{"${p4}u"})) {
					$F[4] = &porturl("${p4}u") . "$pform4</a>";
				}
			}

			$f=0;
			for (@F) {
				printf "  <font color=$color[$f]>$format[$f]", $_;
				$f++;
			}
			print "</font>\n";
		}
	}
	print "</pre></font></b></tt>\n";
	close F;
} else {
	print "<p><font size=+1 color=red><b>ERROR</b>: Cannot open data file for requested data.</font><p>\n";
}


#
#  Complete page (with only form) and leave
#
FINISH_PAGE:
print<<"EOM";
<p><hr noshade><p>
<font size=-1><i>
Maintained by <a href=$MAINT_EMAIL>$MAINT_NAME</a><br>
Updated $UPDATED_DATE;
</i> 
</body></html>
EOM

exit;

#  Compare sort fields
sub fcmp {
	my ($f,$a,$b) = @_;

	die "Invalid sort field<br>\n" if $f==0;

	#  If field number negative, then reverse sort order
	if ($f<0) {
		#  Numeric sort
		$f = -($f);
		$f--;
		if ($format[$f]=~/d$/) {
			return $b <=> $a;
		} else {
			return $b cmp $a;
		}
	} else {
		#  Numeric sort
		$f--;
		if ($format[$f]=~/d$/) {
			return $a <=> $b;
		} else {
			return $a cmp $b;
		}
	}
}


sub porturl {
my ($port) = @_;
return "<a href=\"$cgidir/PortLookup?$port\" onClick=window.open('','popup','height=20,width=360,scrollbars=yes') target='popup'>";

}
