#!/usr/bin/perl ########################################################################## # # # Perl Script for Resend lost Accouting packet to portaone Repius Server # # # # Switzernet(c)2011 # # # ########################################################################## # my modules use strict; use warnings; use POSIX; use Config::IniFiles; use Switch; use DBI; ########################################################################## # Setting my $lock_file = '/var/run/exec-registration.pid'; my $runas_user = 'root'; my $config_file = '/etc/dba/setup-mysql-replication.conf'; ########################################################################## # Globals my ($dbh1,$dbh2,$User,$Pass,$master_host,$master_user,$dba_user,$SYNC_DBA); my @dba_hosts; my @dba_dbh; my $ipaddress; ########################################################################## # 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"; } } 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 "exec-registration.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; } ########################################################################## # 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 { unlink $lock_file ; $dbh1->disconnect or warn "Disconnection failed: $DBI::errstr\n"; $dbh2->disconnect or warn "Disconnection failed: $DBI::errstr\n"; foreach my $tdbh (@dba_dbh) { $tdbh->disconnect or warn "Disconnection failed: $DBI::errstr\n"; } exit; } ########################################################################## # FUNCTION # ########################################################################## # Remove leading and trailing white space from a string sub chomp_plus { my $string=shift; $string =~ s/^\s+//;$string =~ s/\s+$//; chomp $string; return $string; } ########################################################################## # Load config from mysql.conf sub load_config { my $conf=Config::IniFiles->new(-file => $config_file); return 0 if !defined $conf ; $User = $conf->val('SLAVE','User'); $Pass = $conf->val('SLAVE','Pass'); $master_host = $conf->val('MASTER','Master'); $master_user = $conf->val('MASTER','User'); my @ifconfigresult = `/sbin/ifconfig|/bin/grep "addr.*Bcast" -oE`; $ifconfigresult[0] =~ m/addr:([^ ]+)[ ]*Bcast/; my $ipaddress = $1; $dba_user = $conf->val('DBA','User'); @dba_hosts=split(',', $conf->val('DBA','Host')); my $i = 0; foreach my $t (@dba_hosts) { $t=chomp_plus($t); delete $dba_hosts[$i] if ($dba_hosts[$i] eq $ipaddress); $i++; } $SYNC_DBA = $conf->val('DBA','Sync'); if ($SYNC_DBA=~ m/(on|yes|1)/i) {$SYNC_DBA=1;} else {$SYNC_DBA=0}; return 1; } ########################################################################## # Astrad Radius DB connect sub db_connect { my $dbh = DBI->connect_cached("DBI:mysql:".$_[0].";host=".$_[1],$_[2],$_[3]); return $dbh if $dbh ; safe_exit(); } ########################################################################## # sub exec_register { my ($str,$stp)=(0,0); my $req1=' '; my $req2=' '; my @req3; my $sth = $dbh1->prepare("SELECT * FROM registration where dba=(select value from config where name='ipaddr') ORDER BY id LIMIT 30;"); safe_exit() if !$sth->execute(); return 0 if !$sth->rows; while (my $result = $sth->fetchrow_hashref) { $str=$result->{id} if !$str; $stp=$result->{id}; if ($result->{action} eq 'REGISTER') { $result->{useragent} = 'Unknown' if (!defined $result->{useragent}); $req1 .= "('".$result->{username}."','".$result->{domain}."','sip:".$result->{username}.'@'.$result->{ipaddr}.':'.$result->{port}."','".$result->{expires}."',-1.00,'Astrad-V010', 1, 1, '".$result->{useragent}."'),"; push(@req3, "INSERT INTO location2 (username,domain,dba,ipaddr,port,expires,register) VALUES ('".$result->{username}."','".$result->{domain}."','".$result->{dba}."','".$result->{ipaddr}."','".$result->{port}."','".$result->{expires}."','".$result->{register}."') ON DUPLICATE KEY UPDATE expires='".$result->{expires}."', register='".$result->{register}."';"); # push(@req3, "UPDATE location2 SET useragent='".$result->{useragent}."' WHERE username = '".$result->{username}."' AND domain = '".$result->{domain}."' AND dba = '".$result->{dba}."' AND ipaddr = '".$result->{ipaddr}."' AND port = '".$result->{port}."';"); } elsif ($result->{action} eq 'UNREGISTER') { $req2 .= "(username='".$result->{username}."' AND domain='".$result->{domain}."' AND contact='sip:".$result->{username}.'@'.$result->{ipaddr}.':'.$result->{port}."' AND expires='".$result->{expires}."') OR "; push(@req3, "DELETE FROM location2 WHERE username='".$result->{username}."'AND domain='".$result->{domain}."'AND dba='".$result->{dba}."' AND expires='".$result->{expires}."'"); } } $sth->finish; $dbh2->do("REPLACE INTO location (username,domain,contact,expires,q,callid,cseq,flags,user_agent) VALUES ".substr($req1,0,length($req1)-1)) if $req1 ne ' '; $dbh2->do("DELETE FROM location WHERE ".substr($req2,0,length($req2)-3)) if $req2 ne ' '; $dbh1->do("DELETE FROM registration WHERE id BETWEEN $str AND $stp"); return 1 if (!$SYNC_DBA); foreach my $treq (@req3) { foreach my $tdbh (@dba_dbh) { $tdbh->do($treq); } } undef(@req3); return 1; } ########################################################################## # main() # ########################################################################## load_config(); for (my $i=0;$i<30;$i++) { $dbh1=db_connect("astrad","localhost",$User,$Pass); $dbh2=db_connect("porta-sip",$master_host,$master_user,''); if ($SYNC_DBA) { foreach my $t (@dba_hosts) {push(@dba_dbh,db_connect("astrad",$t,$dba_user,'')) if (defined $t);} } $i=0 if exec_register(); sleep 1 if $i; undef(@dba_dbh); } safe_exit(); ########################################################################## # END # ##########################################################################