#!/usr/bin/perl ########################################################################## # # # Perl Script for Radius Accounting # # Switzernet(c)2011 # # # ########################################################################## # my modules use strict; use warnings; use Asterisk::Manager; use Sys::Syslog; use POSIX; use Config::IniFiles; use Authen::Radius; use DBI; use Switch; use threads; use threads::shared; #Enable debug use constant DEBUG => 0; use Data::Dumper; local $Data::Dumper::Indent = 0; #WARNING Variables set by AGI are not correctly read from this script ########################################################################## # Setting my $lock_file = '/var/run/ast-rad-acc.pid'; my $lock_control = '/var/run/ast-control.pid'; my $runas_user = 'root'; my $monitor_dir = '/var/spool/asterisk/monitor'; my $config_dir = '/etc/astrad/config'; ########################################################################## # Globals my %channels; my ($ast_hostname,$ast_username,$ast_password); my ($rad_serv, $rad_sec, $nas_ip); my ($DB_NAME_Rad,$DB_HOST_Rad,$DB_USER_Rad,$DB_PASS_Rad,$dbh_Rad,$Rad_connected); my ($CustomerType,$lconf,$astman,$ast_connected,$thr); my $t_event : shared; my @event_list; ########################################################################## # Initialization # ########################################################################## # Check if already running # if( -e $lock_file ) { open(PID,$lock_file); my $pid=; close PID; chomp $pid; if( !-e "/proc/$pid" ) { print STDERR "Lock file present, but no process with pid=$pid.\n"; die "Can't delete lock file $lock_file\n" if !unlink $lock_file; print STDERR "Lock file has been removed.\n"; } else { die "Lockfile present, another copy is punning pid=$pid\n"; } } load_config(); my ($name, $passwd, $uid, $gid) = getpwnam($runas_user) or die "$runas_user not in passwd file";; ########################################################################## # set C locale POSIX::setlocale(LC_ALL, "C"); ########################################################################## # Become daemon my $pid; if( !defined($pid = fork()) ) { die "cannot fork: $!"; } elsif ($pid) { # Create lockfile, and finish parent process # open(PID, "> $lock_file") || die "ast-rad-acc.pl: Unable to create lockfile $lock_file\n"; print PID "$pid"; close PID; chown $uid, $gid, $lock_file; exit; } else { # daemon setpgrp(); select(STDERR); $| = 1; select(STDOUT); $| = 1; openlog('ast-rad-acc', 'cons,pid', 'daemon'); syslog('notice', "Ast-Rad ast-rad-acc: accounting for Asterisk started"); } ########################################################################## # Install signall handler $SIG{INT} = \&safe_exit; $SIG{QUIT} = \&safe_exit; $SIG{TERM} = \&safe_exit; $SIG{HUP} = \&load_config; ########################################################################## # Drop privileges setuid($uid); $< = $uid; $> = $uid; ########################################################################## # Signal Handlers sub safe_exit { my($sig) = @_; syslog('crit', "Ast-Rad: Caught a SIG$sig - shutting down"); $astman->disconnect if $ast_connected; $dbh_Rad->disconnect if $Rad_connected; unlink $lock_file or syslog('crit', "Ast-Rad: Unable to create lockfile $lock_file\n"); closelog(); exit; } ########################################################################## # FUNCTION # ########################################################################## # Load config sub load_config { my $conf=Config::IniFiles->new(-file => "$config_dir/switzer.conf"); return 0 if !defined $conf ; $rad_serv = $conf->val('MASTER_RD','RADIUS_SERVER'); $rad_sec = $conf->val('MASTER_RD','RADIUS_SECRET'); $nas_ip = $conf->val('GLOBAL','NAS_IP'); $DB_NAME_Rad = $conf->val('ASTER_DB','DB_NAME'); $DB_HOST_Rad = $conf->val('ASTER_DB','DB_HOST'); $DB_USER_Rad = $conf->val('ASTER_DB','DB_USER'); $DB_PASS_Rad = $conf->val('ASTER_DB','DB_PASS'); $ast_hostname = $conf->val('Manager','AMI_PERMIT'); $ast_username = $conf->val('Manager','AMI_USER2'); $ast_password = $conf->val('Manager','AMI_SECRET2'); return 1; } ########################################################################## # sample '09:16:05 GMT Sat Dec 11 2004' sub format_date_gmt { my ($date) = @_; return strftime "%H:%M:%S GMT %a %b %e %Y", gmtime($date); } ########################################################################## # sample '2004-12-11 09:16:05' sub format_date_sql { my ($date) = @_; if ($date eq 0) { return "NULL"; } else { return strftime("%Y-%m-%d %H:%M:%S", localtime($date)); } } ########################################################################## # Astrad Rad. DB connect sub Rad_connect { my $cop=0; $Rad_connected = 1; while( 1 ) { $cop++; $dbh_Rad = DBI->connect_cached("DBI:mysql:$DB_NAME_Rad;host=$DB_HOST_Rad", $DB_USER_Rad, $DB_PASS_Rad); if( $dbh_Rad ) { $Rad_connected = 1; $cop=0; syslog('info', 'Ast-Rad: Connected to Astrad Rad. DB!') if (DEBUG); return 1; } else { if ($Rad_connected) { syslog('err', 'Ast-Rad: Could not connect to Astrad Rad. DB!'); $cop=1; } $Rad_connected = 0; syslog('info', "Ast-Rad: Connection to Astrad Rad. DB -> SLEEP $cop"); $cop++ if $cop; return 0 if ($cop>=3); } sleep 1; } } ########################################################################## # Insert into the Failed radius packets Table sub Failed_radius_packet { my (%data) = @_; return 0 if (!Rad_connect()); $data{'CDR(CustomerType)'}="" if (!defined($data{'CDR(CustomerType)'})); my $request="INSERT INTO radius_packets_Failed (" ."h323_connect_time, h323_disconnect_time, acct_session_time, h323_disconnect_cause, nas_ip_address, user_name, calling_station_id, " ."called_station_id, call_id, h323_setup_time, h323_conf_id, h323_remote_address, call_profile, creation_date, reception_date, " ."last_send, send_counter, status) " ."VALUES " ."('".$data{'H323_connect_time'}."','".$data{'H323_disconnect_time'}."','".$data{'Acct_Session_Time'}."','".$data{'H323_disconnect_cause'} ."','".$data{'nas_ip_address'}."','".$data{'user_name'}."','".$data{'Calling-Station-Id'}."','".$data{'Called-Station-Id'} ."','".$data{'call_id'}."','".$data{'H323_setup_time'}."','".$data{'H323_conf_id'}."','".$data{'H323_remote_address'}."','".$data{'call_profile'} ."','".$data{'creation_date'}."','".$data{'reception_date'}."','".$data{'last_send'}."','".$data{'send_counter'}."','".$data{'status'}."')"; my $sth = $dbh_Rad->prepare($request); if ($sth->execute()) { $sth->finish; syslog('info', "Ast-Rad: Request = $request") if (DEBUG); return 1; } return 0; } ########################################################################## # thread control sub AMI_control { syslog('info', 'Ast-Rad: Thread: Start AMI Control') if (DEBUG); my ($l_event,$cop) = (0,0); while ( 1 ) { $l_event = time(); syslog('info', "Ast-Rad: Thread: Time Events -> Last = $t_event | Now = $l_event") if (DEBUG); #TODO if connection to asterisk is lost the script should not exit if ($l_event - $t_event > 400) { syslog('crit', "Ast-Rad: Thread: Asterisk PBX is probably restarted !"); safe_exit(); } $cop=0 if ($l_event - $t_event < 4); $cop++; syslog('info', "Ast-Rad: Thread: AMI Control sleep $cop") if (DEBUG); sleep 2; } } ########################################################################## # AMI connect sub AMI_connect { $astman = new Asterisk::Manager; $astman->user($ast_username); $astman->secret($ast_password); $astman->host($ast_hostname); $t_event = time(); my $cop=0; $ast_connected = 1; while( 1 ) { $cop++; if( $astman->connect ) { $ast_connected = 1; $cop=0; syslog('info', 'Ast-Rad: Connected to Asterisk!') if (DEBUG); $thr = threads->new(\&AMI_control); $astman->setcallback('DEFAULT', \&status_callback); eval { $astman->eventloop; }; } else { if ($ast_connected) { syslog('err', 'Ast-Rad: Could not connect to Asterisk!'); $cop=1; } $ast_connected = 0; syslog('info', "Ast-Rad: SLEEP $cop"); $cop++ if $cop; return 0 if ($cop>=3); } sleep 1; } } ########################################################################## # sub status_callback { my (%unfiltered_event) = @_; my $status = 0; return if not (%unfiltered_event); $t_event = time(); foreach (keys %unfiltered_event) { next if ($_ eq ''); push(@event_list, [$_, $unfiltered_event{$_}]); } my @event_pos; for my $i ( 0 .. $#event_list) { push(@event_pos, $i) if ($event_list[$i][0] eq 'Event'); } #Remove lines prior to first event my $offset=0; if ($event_pos[0] != 0) { shift(@event_list); $offset++; } while ($#event_pos > 0) { my @filtered_event; print "\n" if (DEBUG); for (my $i = 0; $i < ($event_pos[1]-$offset) ; $i++) { my $addtolist = 1; $addtolist = 0 if ($event_list[0][1] eq 'PeerStatus'); push(@filtered_event, [$event_list[0][0],$event_list[0][1]]) if ($addtolist == 1); print "['".$event_list[0][0]."','".$event_list[0][1]."']\n" if (DEBUG); shift(@event_list); } if ($filtered_event[0][0] eq 'Event') { print "Executing event in filtered_event ".$filtered_event[0][1]."\n" if (DEBUG); switch ($filtered_event[0][1]) { case "Newchannel" { #['Event','Newchannel'] #['Privilege','call,all'] #['Channel','SIP/41215500331-00000013'] #['Context','fromaccount'] #['CallerIDName','41215500331'] #['Uniqueid','91.121.122.64-1324372616.19'] #['ChannelState',''] #['ChannelStateDesc','Down'] #['CallerIDNum','41215500331'] #['Value','sip:41215500331@192.168.1.121:5060'] $channels{$filtered_event[2][1]} = { 'CALLERID' => $filtered_event[8][1], 'UNIQUEID' => $filtered_event[5][1], 'CALL_START' => time(), 'LINK_START' => time(), 'LINK_END' => time(), 'CALL_TYPE' => 'VoIP', 'CALL_PROTOCOL' => 'sipv2', 'CALL_ID' => $filtered_event[5][1], 'RADIUS_Server' => $rad_serv, 'RADIUS_Secret' => $rad_sec, 'NAS_IP_Address' => $nas_ip, 'NAS-Port' => '5060', 'Remoteip' => $nas_ip }; $channels{$filtered_event[2][1]}{'Remoteip'} = $1 if ($filtered_event[2][1] =~ /^SIP\/(\d+\.\d+\.\d+\.\d+)-/i); } case "Newstate" { #['Event','Newstate'] #['Privilege','call,all'] #['Channel','SIP/41215500331-00000013'] #['CallerIDName','41215500331'] #['Uniqueid','91.121.122.64-1324372616.19'] #['ChannelStateDesc','Up'] #['ChannelState','6'] #['CallerIDNum','41215500331'] } case "Newexten" { #['Event','Newexten'] #['Privilege','dialplan,all'] #['Channel','SIP/41215500331-00000011'] #['Context','fromaccount'] #['Extension','0215502419'] #['Uniqueid','91.121.122.64-1324369709.17'] #['Application','Set'] #['AppData','CDR(CustomerType)=SipAuth'] #['Priority','2'] if (defined $filtered_event[7][1] && $filtered_event[6][1] eq 'Set') { my $channel = $filtered_event[2][1]; $channels{$channel}{'DNID'} = $1 if (defined $filtered_event[4][1] && $filtered_event[4][1] =~ /^(\d+)$/); my ( $_var, $_val ) = split(/=/, $filtered_event[7][1]); if ( $_val ne '') { if($_var eq 'CDR(accountcode)') { $channels{$channel}{'ACCOUNTCODE'} = $_val; print '$channels{'.$channel.'}{ACCOUNTCODE} = '.$_val."\n" if (DEBUG); } else { $channels{$channel}{$_var} = $_val; print '$channels{'.$channel.'}{'.$_var.'} = '.$_val."\n" if (DEBUG); if ( $_var eq 'H323_ID') { syslog('debug', "H323 dec: ".$channels{$channel}{'H323_ID'}) if (DEBUG); $channels{$channel}{'H323_ID'}=sprintf("%08X %08X %08X %08X",$1,$2,$3,$4) if $channels{$channel}{'H323_ID'} =~ /(\d+)-(\d+)-(\d+)-(\d+)/; syslog('debug', "H323 hex: ".$channels{$channel}{'H323_ID'}) if (DEBUG); } } } } } case "NewAccountCode" { #['Event','NewAccountCode'] #['Privilege','call,all'] #['Channel','SIP/91.121.151.75-00000014'] #['Uniqueid','91.121.122.64-1324372618.20'] #['Channel2','SIP/91.121.151.75-00000014'] #['Bridgestate','Link'] } case "Link" { #Link does not seem to appear in the new version of asterisk # my $channel1 = $event{'Channel1'}; # my $channel2 = $event{'Channel2'}; # return unless $channels{$channel1}; # $channels{$channel1}{'LINK_START'} = time(); # $channels{$channel2}{'LINK_START'} = time(); # # syslog('info', 'Link without uniqueid') unless $channels{$channel1}{'UNIQUEID'}; # syslog('info', 'Link without channeld') unless $channel1; # syslog('info', 'Link on undefined channel') unless $channels{$channel1}; # # return unless($channel1 && $channels{$channel1} && $channels{$channel1}{'UNIQUEID'}); } case "VarSet" { #['Event','VarSet'] #['Privilege','dialplan,all'] #['Channel','SIP/41215500331-00000011'] #['Uniqueid','91.121.122.64-1324369709.17'] #['Variable','SIPURI'] #['Value','astrad.switzernet.com'] if (defined $filtered_event[5][0] && defined $filtered_event[4][0] && defined $channels{$filtered_event[2][1]}) { $channels{$filtered_event[2][1]}{$filtered_event[4][1]} = $filtered_event[5][1]; print '$channels{'.$filtered_event[2][1].'}{'.$filtered_event[4][1].'} = '.$filtered_event[5][1]."\n" if (DEBUG); } } case "Bridge" { #['Event','Bridge'] #['Privilege','call,all'] #['Uniqueid2','91.121.122.64-1324372618.20'] #['Channel1','SIP/41215500331-00000013'] #['Bridgetype','core'] #['Uniqueid1','91.121.122.64-1324372616.19'] #['CallerID1','41215500331'] #['CallerID2','0215502419'] #['Value','SIP/91.121.151.75-00000014'] if (defined $filtered_event[8][1]) { my $channel1 = $filtered_event[3][1]; my $channel2 = $filtered_event[8][1]; $channels{$channel1}{'LINK_START'} = time(); $channels{$channel1}{'CHANNEL2'} = $channel2; $channels{$channel2}{'CHANNEL1'} = $channel1; $channels{$channel2}{'LINK_START'} = time(); $channels{$channel1}{'CALL_ORIGIN'} = 'answer'; print 'Call '.$channel1." answered. Sending ".$channels{$channel1}{'CALL_ORIGIN'}."-START Radius packet.\n" if (DEBUG); send_acc('Start',%{$channels{$channel1}}); } } case "Unlink" { #['Event','Unlink'] #['Privilege','call,all'] #['Uniqueid2','91.121.122.64-1324372618.20'] #['Channel1','SIP/41215500331-00000013'] #['Uniqueid1','91.121.122.64-1324372616.19'] #['CallerID1','41215500331'] #['CallerID2','0215502419'] #['Value','9'] my $channel = $filtered_event[3][1]; last unless $channels{$channel}; $channels{$channel}{'LINK_END'} = time(); $channels{$channels{$channel}{'CHANNEL2'}}{'LINK_END'} = time() if defined $channels{$channel}{'CHANNEL2'}; } case "Hangup" { #['Event','Hangup']; #['Privilege','call,all']; #['Channel','SIP/91.121.117.76-00000060']; #['Cause','16']; #['ConnectedLineName','41215500331']; #['ConnectedLineNum','41215500331']; #['CallerIDName','']; #['Uniqueid','91.121.122.64-1324045271.96']; #['CallerIDNum','0215502419']; #['Cause-txt','Normal Clearing']; my $channel = $filtered_event[2][1]; $channel = $channels{$channel}{'CHANNEL1'} if (defined $channels{$channel}{'CHANNEL1'}); last if !defined $channels{$channel}; last if !defined $channels{$channel}{'H323_ID'}; $channels{$channel}{'CALL_END'} = time(); $channels{$channel}{'CAUSE'} = 0; $channels{$channel}{'CAUSE'} = $filtered_event[3][1] if $filtered_event[3][1] ne ''; if (defined($channels{$channel}{'CALL_ORIGIN'}) && $channels{$channel}{'CALL_ORIGIN'} eq 'answer') { if (defined $channels{$channel}{'CHANNEL2'}) { print 'Call '.$channel."->".$channels{$channel}{'CHANNEL2'}." disconnected. Sending ".$channels{$channel}{'CALL_ORIGIN'}."-STOP Radius packet.\n" if (DEBUG); delete $channels{$channels{$channel}{'CHANNEL2'}}{'CHANNEL1'}; delete $channels{$channels{$channel}{'CHANNEL2'}}; } else { print 'Call '.$channel." disconnected. Sending ".$channels{$channel}{'CALL_ORIGIN'}."-STOP Radius packet.\n" if (DEBUG); } send_acc('Stop',%{$channels{$channel}}); } $channels{$channel}{'CALL_ORIGIN'} = 'originate'; print 'Call '.$channel." disconnected. Sending ".$channels{$channel}{'CALL_ORIGIN'}."-STOP Radius packet.\n" if (DEBUG); send_acc('Stop',%{$channels{$channel}}); delete $channels{$channel}{'CHANNEL2'}; delete $channels{$channel}; } case "Dial" { #['Event','Dial']; #['DestUniqueID','91.121.122.64-1324045271.96']; #['Privilege','call,all']; #['Destination','SIP/91.121.117.76-00000060']; #['Channel','SIP/41215500331-0000005f']; #['SubEvent','Begin']; #['Dialstring','41215502419@91.121.117.76']; #['ConnectedLineName','']; #['ConnectedLineNum','']; #['CallerIDName','41215500331']; #['UniqueID','91.121.122.64-1324045269.95']; #['CallerIDNum','41215500331']; if ($filtered_event[3][0] ne 'Destination' || $filtered_event[4][0] ne 'Channel' || $filtered_event[5][1] ne 'Begin') { print "End dial\n" if (DEBUG); last; } my $channel1 = $filtered_event[4][1]; my $channel2 = $filtered_event[3][1]; syslog('debug', "DIAL: $channel1 -> $channel2") if (DEBUG); $channels{$channel1}{'VLEG'} = $channel2; $channels{$channel1}{'CALL_ORIGIN'} = 'originate'; $channels{$channel1}{'ACCOUNTCODE'} = $channels{$channel1}{'CALLERID'} if !defined $channels{$channel1}{'ACCOUNTCODE'}; $channels{$channel2}{'ACCOUNTCODE'} = $channels{$channel1}{'ACCOUNTCODE'}; $channels{$channel1}{'CALL_ID'} = $filtered_event[10][1] if !defined $channels{$channel1}{'CALL_ID'}; $channels{$channel2}{'CALL_ID'} = $channels{$channel1}{'CALL_ID'}; $channels{$channel2}{'CALLERID'} = $channels{$channel1}{'CALLERID'}; $channels{$channel2}{'DNID'} = $channels{$channel1}{'VDNID'}; $channels{$channel2}{'H323_ID'} = $channels{$channel1}{'H323_ID'}; $channels{$channel1}{'LINK_START2'} = time(); $channels{$channel2}{'LINK_START2'} = time(); print "Sending ".$channels{$channel1}{'CALL_ORIGIN'}."-START Radius packet.\n" if (DEBUG); #There should be a stop originate for this start even if the call isnt answered or else the call will have a huge length in CDR #send_acc('Start',%{$channels{$channel1}}); } case "Shutdown" { syslog('info', "Asterisk Shutdown"); safe_exit(); } case "Reload" { syslog('info', "Asterisk Reload"); load_config(); } } } undef @filtered_event; shift(@event_pos); } return; } ########################################################################## # sub send_acc { my ($acc_type,%cdr) = @_; my $cause="null"; my $remote; my $duration=0; my $date=0; return if $cdr{'H323_ID'} =~ /(\d+)-(\d+)-(\d+)-(\d+)/; return if !defined $cdr{'CDR(CustomerType)'}; $cdr{'CALL_ORIGIN'} = 'originate' if( !defined $cdr{'CALL_ORIGIN'} ); my $r = new Authen::Radius(Host => $cdr{'RADIUS_Server'}, Secret => $cdr{'RADIUS_Secret'}, TimeOut => 10, Service => 'radius-acct'); if( !defined $r ) { syslog('crit', "RADIUS host $cdr{'RADIUS_Server'} ERROR"); print "RADIUS host ".$cdr{'RADIUS_Server'}." ERROR\n" if (DEBUG); return; } $r->clear_attributes(); return if ($acc_type ne 'Start' && $acc_type ne 'Stop'); print ("Sending Radius ".$cdr{'CALL_ORIGIN'}."->".$acc_type."\n") if (DEBUG); my $CSI = $cdr{'DNID'}; # $CSI = $cdr{'PBCLD'} if ($cdr{'CALL_ORIGIN'} eq "originate"); $CSI = $cdr{'VDNID'} if ($cdr{'CALL_ORIGIN'} eq "originate"); $cdr{'LINK_START2'} = $cdr{'LINK_END'} if (!defined $cdr{'LINK_START2'}); $cdr{'ACCOUNTCODE'} = $cdr{'CALLERID'} if (!defined $cdr{'ACCOUNTCODE'} || $cdr{'ACCOUNTCODE'} eq ''); $r->add_attributes ( { Name => 'Acct-Status-Type', Value => $acc_type }, { Name => 'h323-call-origin', Value => $cdr{'CALL_ORIGIN'} }, { Name => 'h323-call-type', Value => $cdr{'CALL_TYPE'} }, { Name => 'Cisco-AVPair', Value => "h323-session-protocol=".$cdr{'CALL_PROTOCOL'} }, { Name => 'NAS-IP-Address', Value => $cdr{'NAS_IP_Address'} }, { Name => 'NAS-Port', Value => $cdr{'NAS-Port'} }, { Name => 'User-Name', Value => $cdr{'ACCOUNTCODE'} }, { Name => 'Calling-Station-Id', Value => $cdr{'CALLERID'} }, { Name => 'Called-Station-Id', Value => $CSI }, { Name => 'Cisco-AVPair', Value => "call-id=".$cdr{'CALL_ID'} }, { Name => 'Cisco-AVPair', Value => "Acct-Session-Id=".$cdr{'CALL_ID'} }, { Name => 'Cisco-AVPair', Value => "Acct-Delay-Time=0" }, { Name => 'h323-setup-time', Value => format_date_gmt($cdr{'CALL_START'}) }, { Name => 'Cisco-AVPair', Value => "h323-conf-id=".$cdr{'H323_ID'} } ); if ($acc_type eq 'Stop') { # TODO why? $cause = $cdr{'CAUSE'}-6; $cause = 0 if $cause<0; $r->add_attributes ( { Name => 'h323-disconnect-time', Value => format_date_gmt($cdr{'LINK_END'}) }, { Name => 'Acct-Session-Time', Value => $cdr{'LINK_END'} - $cdr{'LINK_START'} }, { Name => 'h323-disconnect-cause', Value => $cause } #TODO h323-voice-quality ); $r->add_attributes ( { Name => 'h323-ivr-out', Value => 'PortaBilling_Session:unlock' } ) if ($cdr{'CALL_ORIGIN'} eq "answer"); $duration=$cdr{'LINK_END'} - $cdr{'LINK_START'}; } $remote = $cdr{'NAS_IP_Address'}; if ($cdr{'CALL_ORIGIN'} eq "originate") { if ($cdr{'ROUTEIP'} eq $cdr{'NAS_IP_Address'}) { $remote = 'sip-ua'; } else { $remote = $cdr{'ROUTEIP'}; } $r->add_attributes ( { Name => 'h323-ivr-out', Value => 'PortaBilling_Auth_CLD:'. $cdr{'PBCLD'}} ) if (defined $cdr{'PBCLD'} && $cdr{'PBCLD'} ne ''); $cdr{'Dial_Info'} =~ m/L\((\d+):/; #The maximum duration of the call is on the wrong field to an Asterisk bug which writes the value of a variable on the previous event when the variable is set from an AGI $r->add_attributes ( { Name => 'h323-ivr-out', Value => 'DURATION:'. substr($1, 0, -3) } ) if defined $1; $r->add_attributes ( { Name => 'h323-connect-time', Value => format_date_gmt($cdr{'LINK_START'}) } ); #TODO alert-timepoint when call starts ringing if start } else { $remote = $cdr{'RECVIP'}; $r->add_attributes ( { Name => 'h323-connect-time', Value => format_date_gmt($cdr{'LINK_START'}) } ); $r->add_attributes ( { Name => 'Cisco-AVPair', Value => "alert-timepoint=".format_date_gmt($cdr{'LINK_START'}) } ); } $r->add_attributes ( { Name => 'h323-remote-address', Value => $remote } ); $date=time; if ($acc_type eq 'Start') { $r->send_packet (ACCOUNTING_REQUEST); } else { $r->send_packet (ACCOUNTING_REQUEST) and my $type = $r->recv_packet; if (!defined $type) { my %data; $data{'H323_setup_time'} = format_date_sql($cdr{'CALL_START'}); $data{'H323_connect_time'} = format_date_sql($cdr{'LINK_START'}); $data{'H323_disconnect_time'} = format_date_sql($cdr{'LINK_END'}); $data{'Acct_Session_Time'} = $cdr{'LINK_END'} - $cdr{'LINK_START'}; $data{'H323_disconnect_cause'} = $cause; $data{'nas_ip_address'} = $cdr{'NAS_IP_Address'}; $data{'user_name'} = $cdr{'ACCOUNTCODE'}; $data{'call_id'} = $cdr{'CALL_ID'}; $data{'H323_conf_id'} = $cdr{'H323_ID'}; $data{'H323_remote_address'} = $remote; $data{'call_profile'} = ""; $data{'call_profile'} = $cdr{'CDR(CustomerType)'} if defined($data{'CDR(CustomerType)'}); $data{'creation_date'} = format_date_sql($date); $data{'reception_date'} = format_date_sql(0); $data{'last_send'} = format_date_sql(time+1); $data{'send_counter'} = 1; $data{'status'} = 0; $data{'Calling-Station-Id'} = $cdr{'CALLERID'}; $data{'Called-Station-Id'} = $CSI; $data{'reception_date'}=0; $data{'STATUS'}=0; syslog('crit', "Ast-Rad: No response from RADIUS server !"); print "Ast-Rad: No response from RADIUS server!\n" if DEBUG; #TODO sometimes it adds several times the same call Failed_radius_packet(%data); } else { print "Ast-Rad: Ast-Rad: Good response from RADIUS server!\n" if DEBUG; syslog('crit', "Ast-Rad: Good response from RADIUS server"); } } } ########################################################################## # main() # ########################################################################## # Load Radius dictionary Authen::Radius->load_dictionary; $lconf=0; while ( 1 ) { if (!$lconf && !load_config()) { syslog('crit', "Ast-Rad: Config file error!"); next; } $lconf=1; if (!AMI_connect()) { syslog('crit', "Ast-Rad: Error in Astrerisk Manager connection"); $lconf=0; sleep 1; } } ########################################################################## # END # ##########################################################################