Re: Accounting scripts for RADIUS detail file

Chris B. Wilson, VectorNet (cbw@vector.net)
Mon, 23 Oct 1995 15:18:04 -0400 (EDT)

On Mon, 23 Oct 1995, Daniel Jacobs wrote:

> 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.

:) it shouldn't take that long.. we do it two ways.. we have a balance
command on the server which tells the users how much time they've used,
and we have a PC based processor integrated with the billing software.
Unfortunatly I don't have the original unmodified version, but Carl at
Livingston sent me a wonderful perl script which takes the detail file
and sums it up for you.

Chris

>
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
>
> #!/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/
>

[-----------------------------------------------------------------------------]
[ Chris B. Wilson http://www.vector.net/~cbw ]
[ Gateway Telecommunications, Inc./VectorNet cbw@vector.net ]
[ New pager number: 904-412-4241 Office: 904-375-8658 ]
[ --------------------------------------------------------------------------- ]