Re: Accounting scripts for RADIUS detail file

Daniel Jacobs (danielj@wizard.com)
Mon, 23 Oct 1995 10:41:47 -0800

If you are using the patches that have been mentioned on the list (sorry,
the coffee has not kicked in - I can't remember the author's name) you
can use the following perl script that I wrote to do accounting. The
users can use it as well to see how long they have been on. It can also
be useful for troubleshooting, to see if someone was actually logged on
correctly and with what protocol. If any one has any ideas for
performance improvements, etc., they are most welcome. As the days in the
log file pile up, it takes longer to run. The summary takes about 3 hours
on a P60 with 48MB RAM.

+++++++++++++++++++++++++++++++++++++++++++++++++++++

#!/bin/perl

#pmaudit version 1.00 9/4/95
#Copyleft Daniel Jacobs 1995. Do with it as you will, give me credit
if
#you feel like it. I'm open to suggestions and tips for improvements.
#Replace $session1 and $session2 with whatever your sessions files
are
#called. The $ARGV[1] with the -f flag is the first three letters of
the
#month you want records for. I back up my sessions files in the same
#directory as sessions.aug, etc.
#You will need to make all the sessions files and the directories
leading
#up to them world-readable.
#I assume no responsibility or liability if this program screws up
your
#system. Although there is no reason it should.
#The 'if ($who eq "root")' stuff is so most users can only audit
themselves.
#The summary takes a while because it stores all the records as an
array
#and then sorts them.
# -h for usage

$data = $total = '';
$session1 = '/var/adm/radacct/pm1.wizard.com/sessions';
$session2 = '/var/adm/radacct/pm2.wizard.com/sessions';
#If you don't have whoami, comment out this line and uncomment the
next one:
chop($who = `/usr/local/bin/whoami`);
#chop($temp = `who am i`); ($who[0]) = split;

if ($ARGV[0] eq "-f") {
$session1 = "/var/adm/radacct/pm1.wizard.com/sessions.$ARGV[1]";
$session2 = "/var/adm/radacct/pm2.wizard.com/sessions.$ARGV[1]";
shift @ARGV; shift @ARGV; }
if ($ARGV[0] eq "") {
&Unshift; &Short; &Exit; }
if ($ARGV[0] eq "-v") {
shift @ARGV;
if ($who eq 'gajake') { if ($ARGV[0] eq "") {&Unshift; }
$suser = 1; &Verbose; &Exit;}
if ($who eq 'root') { if ($ARGV[0] eq "") {&Unshift; } $suser
= 1; &Verbose; &Exit;}
if ($who eq 'danielj') { if ($ARGV[0] eq "") {&Unshift; }
$suser = 1; &Verbose; &Exit;}
&Unshift;
&Verbose; &Exit; }
if ($ARGV[0] eq "-s") {
$session1 = "/var/adm/radacct/pm1.wizard.com/sessions.$ARGV[1]";
$session2 = "/var/adm/radacct/pm2.wizard.com/sessions.$ARGV[1]";
if ($who eq 'root') { &Summary; &Exit; }
if ($who eq 'danielj') { &Summary; &Exit; }
if ($who eq 'gajake') { &Summary; &Exit; }
&Exit; }
if ($ARGV[0] eq "-h") {
&Usage; &Exit; }
else {
if ($who eq 'root') { $suser = 1; &Short; &Exit; }
if ($who eq 'danielj') { $suser = 1; &Short; &Exit; }
if ($who eq 'gajake') { $suser = 1; &Short; &Exit; }
&Unshift; &Short; &Exit;
}

sub Short {
foreach (@ARGV) {
$username = $_; $count = 0;
open(STDIN1,$session1) || die "Can't open $session1: $!\n"
if $session1;
while (read(STDIN1,$data,48)) {
&ShortFind;
}
open(STDIN2,$session2) || die "Can't open $session2: $!\n"
if $session2;
while (read(STDIN2,$data,48)) {
&ShortFind;
}
&TotalTime;
}
}

sub Verbose {
foreach (@ARGV) {
$username = $_; $count = 0;
open(STDIN1,$session1) || die "Can't open $session1: $!\n"
if $session1;
while (read(STDIN1,$data,48)) {
&VerboseFind;
}
open(STDIN2,$session2) || die "Can't open $session2: $!\n"
if $session2;
while (read(STDIN2,$data,48)) {
&VerboseFind;
}
&TotalTime;
}
}

sub Summary {
$count = 0;
open(PASSWD, "/etc/passwd") || die "Can't open passwd file: $!\n";
foreach (<PASSWD>) {
($username) = split(/:/);
open(STDIN1,$session1) || die "Can't open $session1: $!\n"
if $session1;
while (read(STDIN1,$data,48)) {
&SummaryFind;
}
open(STDIN2,$session2) || die "Can't open $session2: $!\n"
if $session2;
while (read(STDIN2,$data,48)) {
&SummaryFind;
}
if ($count == 0) { push (@LIST,"$username did not log in\n"); next; }
$hours = int($total / 3600);
$minutes = int($total % 3600 / 60);
push (@LIST,"$username %02d:%02d\n",$hours,$minutes);
$total = 0;
}
print sort @LIST;
}

sub Unshift {
reset 'A';
$ARGV[0] = $who;
}

sub Exit {
exit;
}

sub Usage {
print "$0:
No arguments: Your usage for the month
-v (verbose): Your detailed usage for the month
-s (summary): Monthly Summary Report
-f <mon> : Usage for previous months
-h : This help (duh!)\n";
}

sub ShortFind {
@userec = unpack('a8S2C4a16a8l4l4',$data);
if ($userec[0] =~ /^$username\W/ || $userec[0] =~ /^$username$/) {
print ".";
if ($userec[10] ne "-1") {
$total = $total + $userec[10]; ++$count; }
if ($userec[10] eq "-1") {
$on = 1; ++$count;
} } }

sub VerboseFind {
@userec = unpack('a8S2C4a16a8l4l4',$data);
if ($userec[0] =~ /^$username\W/ || $userec[0] =~ /^$username$/) {
if ($userec[10] ne "-1") {
$total = $total + $userec[10]; ++$count;
$subhours = int($userec[10] / 3600);
$subminutes = int($userec[10] % 3600 / 60);
$subseconds = $userec[10] % 60; }
if ($userec[10] eq "-1") {
$on = 1;
++$count; }

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime($userec[9]);
($thisday = (Sun,Mon,Tue,Wed,Thu,Fri,Sat)[$wday]);
$thismonth =


("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec")[$mon];
$logintime = "$thisday $thismonth $mday";
if ($userec[2] =~ /1/) { $conn = "LOGIN"; }
elsif ($userec[2] =~ /2/) { $conn = "PPP"; }
elsif ($userec[2] =~ /3/) { $conn = "SLIP"; }
elsif ($userec[2] =~ /4/) { $conn = "CSLIP"; }
elsif ($userec[2] =~ /0/) { $conn = "UNKNOWN"; }
printf "$username 1S$userec[1] $conn $logintime %02d:%02d:%02d -
%02d:%02d:%02d\n",$hour,$min,$sec,$subhours,$subminutes,$subseconds;
} }

sub SummaryFind {
@userec = unpack('a8S2C4a16a8l4l4',$data);
if ($userec[0] =~ /^$username\W/ || $userec[0] =~ /^$username$/) {
if ($userec[10] ne "-1") {
$total = $total + $userec[10]; ++$count; }
if ($userec[10] eq "-1") {
# $ontime = $^T; $total = $total + ($ontime - $userec[9]);
++$count;
}
}
}

sub TotalTime {
if ($count == 0) { print "$username not found.\n"; next; }
$hours = int($total / 3600);
$minutes = int($total % 3600 / 60);
$seconds = $total % 60;
print "\n$username has been on for $hours hours, $minutes minutes,
and $seconds seconds since the 1st.\n";
if ($on && $suser) { print "$username may currently be logged
on.\n"; }
$total = 0; $on = 0;
}
Any sufficiently advanced technology is indistinguishable from magic - PT
World Wide Profile Registry - http://www.wizard.com/wwpr.html
Daniel Jacobs | @wizard.com - Las Vegas Internet Access Provider
sysadmin | (702) 871-4461 or http://snark.wizard.com/