#!/usr/bin/perl use DBI; use Time::Local; use File::Basename; use CGI::Carp qw(cluck); ########################### # SET UP GLOBALS, ETC ETC ########################### $/ = "\cM\cJ"; #FILES ARE ON AN NFS MOUNTED WINDOWS SERVER my $CURRENT = 'Starting the radius detail thingy--no record yet'; #HOLDS ERROR INFO my $DETAIL_FILE = shift || die "Need file name w/ radius recs\n"; #FILE FROM WHICH TO START READING RECs my $NEXT_FILE = get_next_file_name($DETAIL_FILE); #NAME OF DETAIL AFTER MIDNIGHT my $DATABASE_HOST = shift || die "Need host w/ database\n"; #HOST WITH DATABASE my $DATABASE = 'database=radius;' . "host=$DATABASE_HOST"; my $DEBUG = "false"; my $sleepcount = 0; ######################### # INITIALIZE ######################### #CONNECT TO THE DATABASE my $DBH = DBI->connect("dbi:Pg:dbname=radius;host=$DATABASE_HOST", "xxxxxx", "xxxxxx", { RaiseError => 1, AutoCommit => 1, InactiveDestroy => 1} ) or croak "Could not connect to database"; $count = 0; $SQL; open(ACCT, "$DETAIL_FILE"); #SEEK TO EOF seek(ACCT, -1024, 2); #THROW OUT FIRST LINE (MIGHT BE INCOMPLETE) $_ = ; LOOP: for (;;) { for ($curpos = tell(ACCT); $_ = ; $curpos = tell(ACCT)) { my @rec_array = split(/,/, $_); #GET RID OF USELESS TRASH foreach $_ (@rec_array){ $_ =~ s/"//g; $_ =~ s/\s//g; } #TEMP TO FIX USERNAMES WITH "Hex:" $rec_array[7] =~ s/Hex\:.*//; my $ff = substr($rec_array[8], -4); eval { if ($rec_array[3] eq "Start") { $SQL = qq/INSERT INTO online VALUES (/. qq/'$rec_array[0] $rec_array[1]',/. #timestamp qq/'$rec_array[13]',/. #acct_session_id qq/'$rec_array[6]',/. #nas_ip_address qq/'$rec_array[7]',/. #user_name qq/'$rec_array[11]',/. #framed_ip_address qq/'$rec_array[9]',/. #calling_station_id qq/'$rec_array[8]',/. #called_station_id qq/'$ff',/. #final_four qq/'$rec_array[23]'/. #nas_port qq/);/; #$count++; #print "$SQL\n"; $DBH->do($SQL) or croak "Could not Insert: ", caller(), ":", $DBH->errstr, "\n$SQL\n"; } elsif ($rec_array[3] eq "Stop") { my $TABLE = "acct".$ff; $SQL = "DELETE FROM online WHERE acct_session_id='$rec_array[13]' AND nas_ip_address='$rec_array[6]'"; #print "$SQL\n"; $DBH->do($SQL) or croak "Could not delete: ", caller(), ":", $DBH->errstr, "\n"; $SQL = qq/INSERT INTO $TABLE VALUES (/. qq/'$rec_array[0] $rec_array[1]',/. #timestamp qq/'$rec_array[7]',/. #user_name qq/'$rec_array[11]',/. #framed_ip_address qq/'$rec_array[12]',/. #framed_protocol qq/'$rec_array[6]',/. #nas_ip_address qq/'$rec_array[13]',/. #acct_session_id qq/'$rec_array[20]',/. #acct_session_time qq/'$rec_array[21]',/. #acct_input_packets qq/'$rec_array[22]',/. #acct_output_packets qq/'$rec_array[14]',/. #ascend_disconnect_cause qq/'$rec_array[15]',/. #ascend_connect_progress qq/'$rec_array[16]',/. #ascend_xmit_rate qq/'$rec_array[17]',/. #ascend_data_rate qq/'$rec_array[19]',/. #ascend_modem_portno qq/'$rec_array[18]',/. #ascend_modem_slotno qq/'$rec_array[9]',/. #calling_station_id qq/'$rec_array[8]'/. #called_station_id qq/);/; #print "$SQL\n"; $DBH->do($SQL) or croak "Could not Insert: ", caller(), ":", $DBH->errstr, "\n$SQL\n"; #$count++; } }; #TRY TO RECONNECT IF ERROR USING reopen_db() if ($@) { print "Eval Error: $@ $SQL"; next LOOP; } } if (-e $NEXT_FILE){ sleep 3; #SLEEP TO ALLOW OS TO SYNC UP close(ACCT); $DETAIL_FILE = $NEXT_FILE; open (ACCT, "$DETAIL_FILE") || die "couldn't open file: $!\n"; $NEXT_FILE = get_next_file_name($DETAIL_FILE); next; #NEXT FILE DOESN'T EXISTS, SO SLEEP AND TRY AGAIN } else { #IF NO CHANGE IN FILE FOR 60 SECS, RE-OPEN FILE if ($sleepcount > 60) { #RE-OPEN FILE THAT HAS RADIUS INFORMATION open (ACCT, "$DETAIL_FILE") || die "Couldn't open $DETAIL_FILE: $!\n"; #GO ALMOST TO THE END seek(ACCT, -1024, 2); #THROW OUT FIRST LINE (MIGHT BE INCOMPLETE) $_ = ; print "Reopened file. Position: ", tell(ACCT) ,".FIRST LINE: $_\n"; $sleepcount = 0; next; } sleep 1; $sleepcount++; seek(ACCT, $curpos, 0); } } ##################### # EXIT AND CLEAN UP ##################### $DBH->disconnect(); close(ACCT); #print "Inserted $count"; ######################## # get_next_file_name() # DETERMINES THE NAME OF THE NEXT FILE TO TAIL FROM WHEN NEW NAME AT MIDNIGHT # NAME OF FILE SHOULD BE LIKE `/mnt/rad-1/YYYYMMDD.act' ######################## sub get_next_file_name{ #FIND OUT WHERE FILE IS MOUNTED my $path = shift; #PARSE NAME OF FILE my ($base, $dir, $ext) = fileparse($path); #CONFIRM THAT FILE MATCHES THE NUMBER FORMAT $base =~ m/(\d\d\d\d)(\d\d)(\d\d)/ || die "Bad Filename Format: $!\n"; #GENERATE NAME: my ($year, $month, $day) = ($1, $2, $3); #FINDS THE EPOCH SECONDS OF TODAY AT NOON my $curr_day = timelocal(0, 0, 12, $day, $month - 1, $year - 1900 ); #USE THAT NUMBER PLUS A DAYS WORTH OF SECONDS (86400) TO GENERATE TOMMORROW'S DATE NUMBERS my ($new_year, $new_month, $new_day) = (localtime($curr_day + 86399))[5, 4, 3]; #print "Opened new file: ".dirname($path).($new_year + 1900).($new_month + 1).$new_day."\n"; return sprintf("%s/%4.4d%2.2d%2.2d.act", dirname($path) , $new_year + 1900, $new_month + 1, $new_day ); }