#!/opt/bin/perl

# This script contains some code from Lineparser by Dave Anderson
# (angio@aros.net)

# A new approach here, find average length of session by PORT 
# for this month  (only since last cron job ran if readzcat=0)

$readzcat=1;
$maxts=7;
$verbose=0; 
$dropcutoff=120; # 2 mins

# Only this month --- fixme
$m=`date +%m%y`;
chop $m;

print "Scanning for $m..\n";
print "Scan as of " . `date` ;
print "(drop cutoff set at $dropcutoff seconds)\n";

for ($ts=1;$ts<=$maxts;$ts++) {

    printf "Reading from /opt/radius/etc/radacct/ts-$ts.sky.net/detail..\n";
    open(IN, "/opt/radius/etc/radacct/ts-$ts.sky.net/detail") ||
	die "Could not open file for ts-$ts\n";
    &read_data;
    close (IN);

    if ($readzcat) {
	printf "Reading from /opt/radius/etc/radacct/ts-$ts.sky.net/detail-$m.gz..\n";
	open(IN, "zcat /opt/radius/etc/radacct/ts-$ts.sky.net/detail-$m.gz|") ||
	    die "Could not open compressed file for ts-$ts\n";
	&read_data;
	close (IN);
    }
}



# Reconstitute the array into just avg times.. (or medians)
foreach (sort keys %sessions) {
    $num=0;
    $a=0;
    $thisport=$_;

    @s=sort {$a <=> $b} split / /,$sessions{$_};

    # drops
    foreach(@s) { if ($_ < $dropcutoff) { $drops{$thisport}++ } }

    # median
    foreach(@s) { $num++; }
    $median{$_}=@s[int $num/2];  ## median time
    $num{$_}=$num--;

    # mean
    foreach (@s) { $a += $_; }
    $mean{$_}=int $a/($num);
}

# Change drops into percentages..
foreach (keys %drops) {
    $drops{$_}=$drops{$_}/$num{$_}*100;
}

# Find biggest session length for scaling purposes
$max=0;
foreach (keys %median) {
    if ($median{$_} > $max) { $max=$median{$_}; }
}
foreach (keys %mean) {
    if ($mean{$_} > $max) { $max=$mean{$_}; }
}

# Put a ceiling on this, dedicated connections mess up the scale otherwise
if ($max > 7000) { $max=7000; } 

# Draw pretty graphs
print "\n\n\n\n             --- LENGTH OF SESSIONS BY PORT --- \n";
print "          (Longer line == longer sessions == good thing(tm))\n";
print "  O: drops\n  X: mean\n  *: median\n";

foreach (sort keys %mean) {
    $maxwidth=51;

    printf("$_:(%3d sess/%3d %% drops)",$num{$_},$drops{$_});
    $m=$drops{$_}/100*$maxwidth;
    for ($i=0;$i<$m;$i++) { print "O"; }
    print "\n";

    printf("$_:(%3d sess/%3d min avg)",$num{$_},int($mean{$_}/60));
    $m=$mean{$_}/$max*$maxwidth;
    if ($m > $maxwidth) { $m = $maxwidth; }
    for ($i=0;$i<$m;$i++) { print "X"; }
    print "\n";

    printf("$_:(%3d sess/%3d min med)",$num{$_},int($median{$_}/60));
    $m=$median{$_}/$max*$maxwidth;
    if ($m > $maxwidth) { $m = $maxwidth; }
    for ($i=0;$i<$m;$i++) { print "*"; }
    print "\n";
}


############################################################################
sub read_data {
    $begin_record = 1;
    $end_record = 0;

    while (<IN>) {
        chop;
        if (!length($_)) {
	    if ($end_record) {		  
		if ($type eq "Stop") {
		    $this=sprintf("ts%sp%s",$ts,$port);
		    $sessions{$this}=sprintf("%s %s",$sessions{$this},$timeon);
		}
		

	    }
	    $end_record = 0;
	    $begin_record = 1;
	    next;
        }
        if ($begin_record && /^[a-zA-Z]/) {
                ($wday, $month, $mday, $daytime, $year) = split;
                $month = &convert_month($month);
                $year =~ s/19//;
                $date = sprintf("%2.2d/%2.2d/%2.2d",
                        $month, $mday, $year);
                $begin_record = 0;
                $end_record = 1;
                next;
        }
        if ($begin_record) {
                next;
        }
        if (/User-Name/) { 
                s/[^\"]*"([^\"]*).*/$1/;
                s/\s+//g;
                $username = sprintf("%-10s", $_);
                next;
        }
        if (/Acct-Status-Type/) {
                ($type)=/Acct-Status-Type = (\S+)/;
                next;
        }
        if (/Acct-Session-Id/) {
                ($session)=/Acct-Session-Id = \"(\S+)\"/;
                next;
        }
        if (/Client-Port-Id/) {
                s/Client-Port-Id = //;
                $port = sprintf("%2.2d", $_);
                next;
        }
        if (/Framed-Address/) {
                s/Framed-Address = //;
                $host = $_;
        }
        if (/Login-Host/) {
                s/Login-Host = //;
                $host = $_;
        }
        if (/Acct-Session-Time/) {
                s/Acct-Session-Time = //;
                s/\s+//g;
                $timeon = $_;
                next;
        }
}
}


sub convert_month {
	local($_) = $_[0];
	if ($_ eq "Jan") { "01"; }
	elsif ($_ eq "Feb") { "02"; }
	elsif ($_ eq "Mar") { "03"; }
	elsif ($_ eq "Apr") { "04"; }
	elsif ($_ eq "May") { "05"; }
	elsif ($_ eq "Jun") { "06"; }
	elsif ($_ eq "Jul") { "07"; }
	elsif ($_ eq "Aug") { "08"; }
	elsif ($_ eq "Sep") { "09"; }
	elsif ($_ eq "Oct") { "10"; }
	elsif ($_ eq "Nov") { "11"; }
	elsif ($_ eq "Dec") { "12"; }
	else { "-1"; }
}
