diff --git a/setup/radius/OpenSIPS/radacct-patch.sh b/setup/radius/OpenSIPS/radacct-patch.sh index 218d17b..650583a 100755 --- a/setup/radius/OpenSIPS/radacct-patch.sh +++ b/setup/radius/OpenSIPS/radacct-patch.sh @@ -1,67 +1,67 @@ #!/usr/bin/env sh if [ $# -ge 1 ]; then radacct=$1 else radacct='radacct' fi echo -n "Please type in MySQL root password (^C to abort): " read rootpass echo "Patching table $radacct..." mysql -u root -p$rootpass radius << EOF # Fields required for SIP support alter table $radacct add column SipMethod varchar(50) not null; alter table $radacct add column SipResponseCode smallint unsigned not null; alter table $radacct add column SipToTag varchar(128) not null; alter table $radacct add column SipFromTag varchar(128) not null; alter table $radacct add column SipTranslatedRequestURI varchar(255) NOT NULL; alter table $radacct add column SipUserAgents varchar(128) NOT NULL; alter table $radacct add column SipApplicationType varchar(64) NOT NULL; alter table $radacct add column SipCodecs varchar(255) NOT NULL; -alter table $radacct add column SipRPID varchar(25) not null; -alter table $radacct add column SipRPIDHeader varchar(25) not null; +alter table $radacct add column SipRPID varchar(255) not null; +alter table $radacct add column SipRPIDHeader varchar(255) not null; alter table $radacct add column SourceIP varchar(64) not null; alter table $radacct add column SourcePort varchar(5) not null; alter table $radacct add column CanonicalURI varchar(255) not null; alter table $radacct add column DelayTime varchar(5) not null; # Fields required for normalization alter table $radacct add column Timestamp bigint(20) unsigned not null; alter table $radacct add column DestinationId varchar(255) not null; alter table $radacct add column Rate text not null; alter table $radacct add column Price double(20,4) not null; alter table $radacct add Normalized enum('0','1') default '0'; alter table $radacct add BillingId varchar(255) NOT NULL default ''; alter table $radacct add column MediaInfo varchar(32) default NULL; alter table $radacct add column RTPStatistics text not null; alter table $radacct add column FromHeader varchar(128) not null; alter table $radacct add column UserAgent varchar(128) not null; alter table $radacct add column Contact varchar(128) not null; # Enlarge some small columns alter table $radacct change column AcctSessionId AcctSessionId varchar(255) not null; alter table $radacct change column NASPortType NASPortType varchar(255) not null; alter table $radacct change column NASPortId NASPortId varchar(50) not null; alter table $radacct change column AcctUniqueId AcctUniqueId varchar(255) not null; alter table $radacct change column FramedProtocol ENUMtld varchar(64) not null; alter table $radacct add unique sess_id(AcctSessionId(128),SipFromTag,SipToTag) ; alter table $radacct add index caller_idx (CallingStationId); alter table $radacct add index called_idx (CalledStationId); alter table $radacct add index canon_idx (CanonicalURI); alter table $radacct add index normalize_idx(Normalized); alter table $radacct add index source_ip_idx (SourceIP); alter table $radacct add index billing_id_idx (BillingId); alter table $radacct add index dest_id_idx (DestinationId); alter table $radacct add index MediaInfo_idx(MediaInfo); alter table $radacct add index Realm_idx(Realm); EOF echo "done" diff --git a/setup/radius/OpenSIPS/radius_accounting.proc b/setup/radius/OpenSIPS/radius_accounting.proc index 70de737..982cff8 100644 --- a/setup/radius/OpenSIPS/radius_accounting.proc +++ b/setup/radius/OpenSIPS/radius_accounting.proc @@ -1,923 +1,926 @@ /* LAST UPDATED: 2020-06-11 Added TLS-Common-Name -> AcctAuthentic CHANGELOG: - Added support for using usec when no Start/Stop time are given by radius. - Set case statement for update block in "proc_update_raddact_record_mediaproxy" when MediaInfo value passed to query is 'ICE session' - Added SipApplicationType, FromHeader and UserAgent - Added database name as parameter to stored procedures - Fixed the multiple query result in "update_raddact_record_mediaproxy" - Modus operandi update - Fixed determination of previous year in "update_raddact_record_mediaproxy" - Consolidate SET statements to minimize binary log entries - Fixed bug in update_raddact_record_mediaproxy, the record values were reset after execution of update on the first table causing failure to update the previous table Starting with version CDRTool version 4.9 it is possible to store call details records in automatically rotated radacct tables by using MySQL stored procedures. This implementation has been contributed by Andrew Madison How to setup auto-rotation -------------------------- 1. Load radius_accounting.proc into the mysql server. MySQL >=5.0 version and SUPER priviledges are required. 2. Patch the Freeradius server mysql client to allow stored procedures. Instructions can be found in ../freeradius directory. Re-compile and re-install Freeradius server. 3. Copy sql.conf to Freeradius server configuration folder. Edit the new sql.conf with the database connection information. 4. Update MediaProxy configuration to use radius accounting, instead of database accounting (MediaProxy >= 1.8.0 is required) 5. In CDRTool, change global.inc table name to: "table" => "radacct".date("Ym"), The modus operandi of the stored procedure ------------------------------------------ Currently, call detail records generated by the OpenSIPS SIP Proxy are stored into a central radius.radacct table. The radacct table grows and must be manually purged, the purge operation locks the table for writing, which is blocking the application that performs the queries, and this situation is unacceptable. The radacct tables are populated with data as follows: When a SIP session starts, an INSERT query generated by the Freeradius server inserts data into MySQL a radacctYYYYMM table (e.g. radacct200611). Later, when the SIP session ends, an UPDATE query sets various fields of the previously inserted record. The server that performs the INSERT matches the inserted data based on indexes present in the table. We want to store the data in monthly tables that have a name based on the following syntax: radacct%Y%m Examples: radacct200611 (November table) radacct200612 (December table) The stored procedure achieves the following: On INSERT the monthly table is created automatically when necessary. If an INSERT query fails with the mysql code table not available, the right table is created and the INSERT query is performed in the new table. The table name is derived from the current month, which is determined from the AcctStartTime radius attribute. On UPDATE the procedure detects if the UPDATE query has failed because the record does not exist in the current table and updates the record in the previous table by substracting one calendar month, redefining the table name and retry the query. The table name is derived from the AcctStopTime radius attribute. A example of queries on how the procedures can be used is available at the end of this script. */ -- OPTIONAL (COMMENT OUT): DATABASE TO USE -- USE radius; -- MUST FOR UNIX BASED SYSTEMS -- (SEE: http://dev.mysql.com/doc/refman/5.0/en/stored-procedure-logging.html) -- SET GLOBAL log_bin_trust_function_creators = 1; DELIMITER ; -- CREATE "BEGINNING OF DEFAULT TABLE NAME" FUNCTION DROP FUNCTION IF EXISTS `set_radacct_table_name`; DELIMITER $$ CREATE FUNCTION `set_radacct_table_name`() RETURNS varchar(50) DETERMINISTIC BEGIN DECLARE tblname VARCHAR(50); SET tblname = 'radacct'; RETURN tblname; END $$ DELIMITER ; -- CREATE SUPPORT "CREATE TABLE" PROCEDURE DROP PROCEDURE IF EXISTS `create_radacct_table`; DELIMITER $$ CREATE PROCEDURE `create_radacct_table`(IN var_tbl VARCHAR(50)) BEGIN SET @stbl = CONCAT("CREATE TABLE IF NOT EXISTS ", var_tbl, " ( `RadAcctId` bigint(21) NOT NULL auto_increment, `AcctSessionId` varchar(255) NOT NULL default '', `AcctUniqueId` varchar(255) NOT NULL default '', `UserName` varchar(64) NOT NULL default '', `Realm` varchar(64) default '', `NASIPAddress` varchar(15) NOT NULL default '', `NASPortId` varchar(50) NOT NULL default '', `NASPortType` varchar(255) NOT NULL default '', `AcctStartTime` datetime NOT NULL default '0000-00-00 00:00:00', `AcctStopTime` datetime NOT NULL default '0000-00-00 00:00:00', `AcctSessionTime` int(12) default NULL, `AcctAuthentic` varchar(32) default NULL, `ConnectInfo_start` varchar(32) default NULL, `ConnectInfo_stop` varchar(32) default NULL, `AcctInputOctets` bigint(12) default NULL, `AcctOutputOctets` bigint(12) default NULL, `CalledStationId` varchar(50) NOT NULL default '', `CallingStationId` varchar(50) NOT NULL default '', `AcctTerminateCause` varchar(32) NOT NULL default '', `ServiceType` varchar(32) default NULL, `ENUMtld` varchar(64) default NULL, `FramedIPAddress` varchar(15) NOT NULL default '', `AcctStartDelay` int(12) default NULL, `AcctStopDelay` int(12) default NULL, `SipMethod` varchar(50) NOT NULL default '', `SipResponseCode` smallint(5) unsigned NOT NULL default '0', `SipToTag` varchar(128) NOT NULL default '', `SipFromTag` varchar(128) NOT NULL default '', `SipTranslatedRequestURI` varchar(255) NOT NULL default '', `SipUserAgents` varchar(255) NOT NULL default '', `SipApplicationType` varchar(255) NOT NULL default '', `SipCodecs` varchar(255) NOT NULL default '', `SipRPID` varchar(255) NOT NULL default '', `SipRPIDHeader` varchar(255) NOT NULL default '', `SourceIP` varchar(255) NOT NULL default '', `SourcePort` varchar(255) NOT NULL default '', `CanonicalURI` varchar(255) NOT NULL default '', `DelayTime` varchar(5) NOT NULL default '', `Timestamp` bigint(20) NOT NULL default '0', `DestinationId` varchar(15) NOT NULL default '', `Rate` text NOT NULL, `Price` double(20,4) default NULL, `Normalized` enum('0','1') default '0', `BillingId` varchar(255) NOT NULL default '', `MediaInfo` varchar(32) default NULL, `RTPStatistics` text NOT NULL, `FromHeader` varchar(128) NOT NULL default '', `UserAgent` varchar(128) NOT NULL default '', `Contact` varchar(128) NOT NULL default '', PRIMARY KEY (`RadAcctId`), UNIQUE KEY `sess_id` (`AcctSessionId`(128),`SipFromTag`,`SipToTag`), KEY `UserName` (`UserName`), KEY `AcctSessionId` (`AcctSessionId`), KEY `AcctUniqueId` (`AcctUniqueId`), KEY `AcctStartTime` (`AcctStartTime`), KEY `AcctStopTime` (`AcctStopTime`), KEY `NASIPAddress` (`NASIPAddress`), KEY `caller_idx` (`CallingStationId`), KEY `called_idx` (`CalledStationId`), KEY `canon_idx` (`CanonicalURI`), KEY `source_ip_idx` (`SourceIP`), KEY `billing_id_idx` (`BillingId`), KEY `dest_id_idx` (`DestinationId`), KEY `sip_req_uri_idx` (`SipTranslatedRequestURI`), KEY `normalize_idx` (`Normalized`), KEY `MediaInfo_idx` (`MediaInfo`), KEY `Realm_idx` (`Realm`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1"); PREPARE ctbl_stmt FROM @stbl; EXECUTE ctbl_stmt; DEALLOCATE PREPARE ctbl_stmt; END $$ DELIMITER ; -- CREATE SUPPORT "CREATE TABLE" PROCEDURE DROP PROCEDURE IF EXISTS `create_radacct_table_usec`; DELIMITER $$ CREATE PROCEDURE `create_radacct_table_usec`(IN var_tbl VARCHAR(50)) BEGIN SET @stbl = CONCAT("CREATE TABLE IF NOT EXISTS ", var_tbl, " ( `RadAcctId` bigint(21) NOT NULL auto_increment, `AcctSessionId` varchar(255) NOT NULL default '', `AcctUniqueId` varchar(255) NOT NULL default '', `UserName` varchar(64) NOT NULL default '', `Realm` varchar(64) default '', `NASIPAddress` varchar(15) NOT NULL default '', `NASPortId` varchar(50) NOT NULL default '', `NASPortType` varchar(255) NOT NULL default '', `AcctStartTime` varchar(26) NOT NULL default '0000-00-00 00:00:00.000000', `AcctStopTime` varchar(26) NOT NULL default '0000-00-00 00:00:00.000000', `AcctSessionTime` decimal(32,6) not NULL default 0, `AcctAuthentic` varchar(32) default NULL, `ConnectInfo_start` varchar(32) default NULL, `ConnectInfo_stop` varchar(32) default NULL, `AcctInputOctets` bigint(12) default NULL, `AcctOutputOctets` bigint(12) default NULL, `CalledStationId` varchar(50) NOT NULL default '', `CallingStationId` varchar(50) NOT NULL default '', `AcctTerminateCause` varchar(32) NOT NULL default '', `ServiceType` varchar(32) default NULL, `ENUMtld` varchar(64) default NULL, `FramedIPAddress` varchar(15) NOT NULL default '', `AcctStartDelay` int(12) default NULL, `AcctStopDelay` int(12) default NULL, `SipMethod` varchar(50) NOT NULL default '', `SipResponseCode` smallint(5) unsigned NOT NULL default '0', `SipToTag` varchar(128) NOT NULL default '', `SipFromTag` varchar(128) NOT NULL default '', `SipTranslatedRequestURI` varchar(255) NOT NULL default '', `SipUserAgents` varchar(255) NOT NULL default '', `SipApplicationType` varchar(255) NOT NULL default '', `SipCodecs` varchar(255) NOT NULL default '', `SipRPID` varchar(255) NOT NULL default '', `SipRPIDHeader` varchar(255) NOT NULL default '', `SourceIP` varchar(255) NOT NULL default '', `SourcePort` varchar(255) NOT NULL default '', `CanonicalURI` varchar(255) NOT NULL default '', `DelayTime` varchar(5) NOT NULL default '', `Timestamp` bigint(20) NOT NULL default '0', `DestinationId` varchar(15) NOT NULL default '', `Rate` text NOT NULL, `Price` double(20,4) default NULL, `Normalized` enum('0','1') default '0', `BillingId` varchar(255) NOT NULL default '', `MediaInfo` varchar(32) default NULL, `RTPStatistics` text NOT NULL, `FromHeader` varchar(128) NOT NULL default '', `UserAgent` varchar(128) NOT NULL default '', `Contact` varchar(128) NOT NULL default '', PRIMARY KEY (`RadAcctId`), UNIQUE KEY `sess_id` (`AcctSessionId`(128),`SipFromTag`,`SipToTag`), KEY `UserName` (`UserName`), KEY `AcctSessionId` (`AcctSessionId`), KEY `AcctUniqueId` (`AcctUniqueId`), KEY `AcctStartTime` (`AcctStartTime`), KEY `AcctStopTime` (`AcctStopTime`), KEY `NASIPAddress` (`NASIPAddress`), KEY `caller_idx` (`CallingStationId`), KEY `called_idx` (`CalledStationId`), KEY `canon_idx` (`CanonicalURI`), KEY `source_ip_idx` (`SourceIP`), KEY `billing_id_idx` (`BillingId`), KEY `dest_id_idx` (`DestinationId`), KEY `sip_req_uri_idx` (`SipTranslatedRequestURI`), KEY `normalize_idx` (`Normalized`), KEY `MediaInfo_idx` (`MediaInfo`), KEY `Realm_idx` (`Realm`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1"); PREPARE ctbl_stmt FROM @stbl; EXECUTE ctbl_stmt; DEALLOCATE PREPARE ctbl_stmt; END $$ DELIMITER ; -- CREATE "INSERT RECORD" PROCEDURE DROP PROCEDURE IF EXISTS `insert_radacct_record`; DELIMITER $$ CREATE PROCEDURE `insert_radacct_record`( IN var_db_name VARCHAR(20), IN var_AcctSessionId VARCHAR(255), IN var_AcctUniqueId VARCHAR(255), IN var_UserName VARCHAR(64), IN var_Realm VARCHAR(64), IN var_NASIPAddress VARCHAR(15), IN var_NASPortId VARCHAR(50), IN var_AcctStartTime VARCHAR(26), IN var_AcctStopTime VARCHAR(26), IN var_AcctSessionTime DECIMAL(32,6), IN var_AcctInputOctets BIGINT(12), IN var_AcctOutputOctets BIGINT(12), IN var_AcctAuthentic VARCHAR(32), IN var_CalledStationId VARCHAR(50), IN var_CallingStationId VARCHAR(50), IN var_AcctTerminateCause VARCHAR(32), IN var_ServiceType VARCHAR(32), IN var_ENUMtld VARCHAR(64), IN var_FramedIPAddress VARCHAR(15), IN var_AcctStartDelay INT(12), IN var_AcctStopDelay INT(12), IN var_SipResponseCode SMALLINT(5), IN var_SipMethod VARCHAR(50), IN var_SipTranslatedRequestURI VARCHAR(255), IN var_SipToTag VARCHAR(128), IN var_SipFromTag VARCHAR(128), IN var_SipRPID VARCHAR(255), + IN var_SipRPIDHeader VARCHAR(255), IN var_SourceIP VARCHAR(255), IN var_SourcePort VARCHAR(255), IN var_CanonicalURI VARCHAR(255), IN var_Rate TEXT, IN var_RTPStatistics TEXT, IN var_SipApplicationType TEXT, IN var_UserAgent TEXT, IN var_FromHeader TEXT ) BEGIN -- SET VARIABLES SET @v_AcctSessionId = var_AcctSessionId, @v_AcctUniqueId = var_AcctUniqueId, @v_UserName = var_UserName, @v_Realm = var_Realm, @v_NASIPAddress = var_NASIPAddress, @v_NASPortId = var_NASPortId; IF var_AcctStartTime = '0' OR var_AcctStartTime = '' THEN SET @v_AcctStartTime = now_usec(), @usec=1; ELSE SET @v_AcctStartTime = CAST(var_AcctStartTime AS DATETIME); END IF; IF (var_AcctStopTime = '0' ) AND ( var_AcctStartTime = '' ) THEN SET @v_AcctStopTime = '0000-00-00 00:00:00.000000' ; ELSE IF (var_AcctStopTime = '' ) AND ( var_AcctStartTime = '' ) THEN SET @v_AcctStopTime = @v_AcctStartTime; ELSE IF var_AcctStopTime = '0' OR var_AcctStopTime = '' THEN SET @v_AcctStopTime = CAST('0000-00-00 00:00:00' AS DATETIME); ELSE SET @v_AcctStopTime = CAST(var_AcctStopTime AS DATETIME); END IF; END IF; END IF; SET @v_db_name = var_db_name, @v_AcctSessionTime = var_AcctSessionTime, @v_AcctInputOctets = var_AcctInputOctets, @v_AcctOutputOctets = var_AcctOutputOctets, @v_AcctAuthentic = var_AcctAuthentic, @v_CalledStationId = var_CalledStationId, @v_CallingStationId = var_CallingStationId, @v_AcctTerminateCause = var_AcctTerminateCause, @v_ServiceType = var_ServiceType, @v_ENUMtld = var_ENUMtld, @v_FramedIPAddress = var_FramedIPAddress, @v_AcctStartDelay = var_AcctStartDelay, @v_AcctStopDelay = var_AcctStopDelay, @v_SipResponseCode = var_SipResponseCode, @v_SipMethod = var_SipMethod, @v_SipTranslatedRequestURI = var_SipTranslatedRequestURI, @v_SipToTag = var_SipToTag, @v_SipFromTag = var_SipFromTag, @v_SipRPID = var_SipRPID, + @v_SipRPIDHeader = var_SipRPIDHeader, @v_SourceIP = var_SourceIP, @v_SourcePort = var_SourcePort, @v_CanonicalURI = var_CanonicalURI, @v_Rate = var_Rate, @v_RTPStatistics = var_RTPStatistics, @v_SipApplicationType = var_SipApplicationType, @v_UserAgent = var_UserAgent, @v_FromHeader = var_FromHeader, @var_y = (SELECT YEAR(@v_AcctStartTime)), @var_m = (SELECT DATE_FORMAT(@v_AcctStartTime, '%m')), @var_tbl_begin = (SELECT set_radacct_table_name()), @var_tbl = CONCAT(@var_tbl_begin, @var_y, @var_m), @var_tbl_cnt = (SELECT COUNT(TABLE_NAME) AS TBLCNT FROM information_schema.tables WHERE TABLE_SCHEMA = @v_db_name AND TABLE_NAME = @var_tbl); -- TABLE DOES NOT EXIST IF @var_tbl_cnt = 0 THEN IF @usec=1 THEN -- CREATE RAD TABLE FOR USEC SET @ctblproc = CONCAT("CALL create_radacct_table_usec(", "'", @var_tbl, "'", ")"); PREPARE ctbl_proc_stmt FROM @ctblproc; EXECUTE ctbl_proc_stmt; DEALLOCATE PREPARE ctbl_proc_stmt; ELSE -- CREATE RAD TABLE SET @ctblproc = CONCAT("CALL create_radacct_table(", "'", @var_tbl, "'", ")"); PREPARE ctbl_proc_stmt FROM @ctblproc; EXECUTE ctbl_proc_stmt; DEALLOCATE PREPARE ctbl_proc_stmt; END IF; END IF; -- INSERT RECORD IN NEW TABLE SET @instmt = CONCAT("INSERT INTO ", @var_tbl, " ( RadAcctId, AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, AcctStartTime, AcctStopTime, AcctSessionTime, AcctInputOctets, AcctOutputOctets, AcctAuthentic, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, ENUMtld, FramedIPAddress, AcctStartDelay, AcctStopDelay, SipResponseCode, SipMethod, SipTranslatedRequestURI, SipToTag, - SipFromTag, SipRPID, SourceIP, SourcePort, CanonicalURI, + SipFromTag, SipRPID, SipRPIDHeader, SourceIP, SourcePort, CanonicalURI, Rate, RTPStatistics, SipApplicationType, UserAgent, FromHeader) VALUES (NULL, ?, ?, ?, SUBSTRING_INDEX(?, '@',-1), ?, ?, ?, ?, ?, ?, ?, ?, trim(leading 'sip:' from trim(leading 'sips:' from ?)), trim(leading 'sip:' from trim(leading 'sips:' from ?)), ?, ?, ?, ?, ?, ?, ?, ?, trim(leading 'sip:' from trim(leading 'sips:' from ?)), - ?, ?, ?, ?, ?, trim(leading 'sip:' from trim(leading 'sips:' from ?)), ?, ?, ?, ?, ? + ?, ?, ?, ?, ?, ?, trim(leading 'sip:' from trim(leading 'sips:' from ?)), ?, ?, ?, ?, ? )"); PREPARE add_rad FROM @instmt; EXECUTE add_rad USING @v_AcctSessionId, @v_AcctUniqueId, @v_UserName, @v_Realm, @v_NASIPAddress, @v_NASPortId, @v_AcctStartTime, @v_AcctStopTime, @v_AcctSessionTime, @v_AcctInputOctets, @v_AcctOutputOctets, @v_AcctAuthentic, @v_CalledStationId, @v_CallingStationId, @v_AcctTerminateCause, @v_ServiceType, @v_ENUMtld, @v_FramedIPAddress, @v_AcctStartDelay, @v_AcctStopDelay, @v_SipResponseCode, @v_SipMethod, @v_SipTranslatedRequestURI, @v_SipToTag, @v_SipFromTag, - @v_SipRPID, @v_SourceIP, @v_SourcePort, @v_CanonicalURI, + @v_SipRPID, @v_SipRPIDHeader, @v_SourceIP, @v_SourcePort, @v_CanonicalURI, @v_Rate, @v_RTPStatistics, @v_SipApplicationType, @v_UserAgent, @v_FromHeader; DEALLOCATE PREPARE add_rad; -- CLEAN UP SET @v_AcctSessionId = null, @usec=null, @v_AcctUniqueId = null, @v_UserName = null, @v_Realm = null, @v_NASIPAddress = null, @v_NASPortId = null, @v_AcctStartTime = null, @v_AcctStopTime = null, @v_AcctSessionTime = null, @v_AcctInputOctets = null, @v_AcctOutputOctets = null, @v_AcctAuthentic = null, @v_CalledStationId = null, @v_CallingStationId = null, @v_AcctTerminateCause = null, @v_ServiceType = null, @v_ENUMtld = null, @v_FramedIPAddress = null, @v_AcctStartDelay = null, @v_AcctStopDelay = null, @v_SipResponseCode = null, @v_SipMethod = null, @v_SipTranslatedRequestURI = null, @v_SipToTag = null, @v_SipFromTag = null, @v_SipRPID = null, + @v_SipRPIDHeader = null, @v_SourceIP = null, @v_SourcePort = null, @v_CanonicalURI = null, @v_Rate = null, @v_RTPStatistics = null, @v_SipApplicationType = null, @v_UserAgent = null, @v_FromHeader = null, @var_y = null, @var_m = null, @v_db_name = null, @var_tbl_begin = null, @var_tbl = null; END $$ DELIMITER ; -- CREATE "UPDATE RECORD" PROCEDURE DROP PROCEDURE IF EXISTS `update_radacct_record`; DELIMITER $$ CREATE PROCEDURE `update_radacct_record`( IN var_db_name VARCHAR(20), IN var_AcctStopTime VARCHAR(26), IN var_AcctStopDelay INT(12), IN var_ConnectInfo_stop VARCHAR(32), IN var_RTPStatistics VARCHAR(255), IN var_AcctSessionId VARCHAR(255), IN var_SipToTag VARCHAR(128), IN var_SipFromTag VARCHAR(128) ) BEGIN -- SET VARIABLES IF var_AcctStopTime = '0' OR var_AcctStopTime = '' THEN SET @v_AcctStopTime = now_usec(), @v_stoptime = @v_AcctStopTime, @usec=1; ELSE SET @v_AcctStopTime = CAST(var_AcctStopTime AS DATETIME), @v_stoptime = var_AcctStopTime; END IF; SET @v_db_name = var_db_name, @var_tbl_begin = (SELECT set_radacct_table_name()), @var_month_formatted = (SELECT DATE_FORMAT(@v_stoptime, '%m')), @var_yst = (SELECT DATE_FORMAT(@v_stoptime, '%Y')), @var_tbl_month = CONCAT(@var_tbl_begin, @var_yst, @var_month_formatted), @v_AcctStopDelay = var_AcctStopDelay, @v_RTPStatistics = var_RTPStatistics, @v_AcctSessionId = var_AcctSessionId, @v_SipToTag = var_SipToTag, @v_SipFromTag = var_SipFromTag, @var_tbl_cnt1 = (SELECT COUNT(TABLE_NAME) AS TBLCNT FROM information_schema.tables WHERE TABLE_SCHEMA = @v_db_name AND TABLE_NAME = @var_tbl_month); IF @var_tbl_cnt1 = 1 THEN -- WE HAVE A TABLE BASED ON StopTime -- SO LET'S TRY TO UPDATE IF @usec=1 THEN SET @updstmt1 = CONCAT("UPDATE ", @var_tbl_month, " SET AcctStopTime = ?, AcctSessionTime = CONCAT( TIME_TO_SEC(TIMEDIFF(?, AcctStartTime)), '.', MICROSECOND(TIMEDIFF(?, AcctStartTime)) ), AcctStopDelay = ?, ConnectInfo_stop = '', RTPStatistics = ?, Normalized = '0' WHERE AcctSessionId = ? AND ((SipToTag = ? AND SipFromTag = ?) OR (SipToTag = ? AND SipFromTag = ?)) AND ConnectInfo_stop IS NULL AND (MediaInfo IS NULL OR MediaInfo != 'timeout');"); PREPARE update_rad1 FROM @updstmt1; EXECUTE update_rad1 USING @v_AcctStopTime, @v_AcctStopTime, @v_AcctStopTime, @v_AcctStopDelay, @v_RTPStatistics, @v_AcctSessionId, @v_SipToTag, @v_SipFromTag, @v_SipFromTag, @v_SipToTag; ELSE SET @updstmt1 = CONCAT("UPDATE ", @var_tbl_month, " SET AcctStopTime = ?, AcctSessionTime = UNIX_TIMESTAMP(?) - UNIX_TIMESTAMP(AcctStartTime), AcctStopDelay = ?, ConnectInfo_stop = '', RTPStatistics = ?, Normalized = '0' WHERE AcctSessionId = ? AND ((SipToTag = ? AND SipFromTag = ?) OR (SipToTag = ? AND SipFromTag = ?)) AND ConnectInfo_stop IS NULL AND (MediaInfo IS NULL OR MediaInfo != 'timeout');"); PREPARE update_rad1 FROM @updstmt1; EXECUTE update_rad1 USING @v_AcctStopTime, @v_AcctStopTime, @v_AcctStopDelay, @v_RTPStatistics, @v_AcctSessionId, @v_SipToTag, @v_SipFromTag, @v_SipFromTag, @v_SipToTag; END IF; SET @updatedrows = (SELECT ROW_COUNT()), @updstmt1 = null; DEALLOCATE PREPARE update_rad1; ELSE SET @updatedrows = 0; END IF; IF @updatedrows = 0 THEN -- UPDATE LAST MONTH'S TABLE BASED ON var_AcctStopTime SET @var_prev_month = (SELECT DATE_FORMAT(DATE_ADD(@v_stoptime, INTERVAL -1 MONTH), '%Y%m')), @var_tbl_pmonth = CONCAT(@var_tbl_begin, @var_prev_month), @var_tbl_cnt2 = (SELECT COUNT(TABLE_NAME) AS TBLCNT FROM information_schema.tables WHERE TABLE_SCHEMA = @v_db_name AND TABLE_NAME = @var_tbl_pmonth); IF @var_tbl_cnt2 = 1 THEN -- UPDATE PREVIOUS MONTH TABLE IF @usec=1 THEN SET @updstmt2 = CONCAT("UPDATE ", @var_tbl_pmonth, " SET AcctStopTime = ?, AcctSessionTime = CONCAT( TIME_TO_SEC(TIMEDIFF(?, AcctStartTime)), '.', MICROSECOND(TIMEDIFF(?, AcctStartTime))), AcctStopDelay = ?, ConnectInfo_stop = '', RTPStatistics = ?, Normalized = '0' WHERE AcctSessionId = ? AND ((SipToTag = ? AND SipFromTag = ?) OR (SipToTag = ? AND SipFromTag = ?)) AND ConnectInfo_stop IS NULL AND (MediaInfo IS NULL OR MediaInfo != 'timeout') ;"); PREPARE update_rad2 FROM @updstmt2; EXECUTE update_rad2 USING @v_AcctStopTime, @v_AcctStopTime, @v_AcctStopTime, @v_AcctStopDelay, @v_RTPStatistics, @v_AcctSessionId, @v_SipToTag, @v_SipFromTag, @v_SipFromTag, @v_SipToTag; ELSE SET @updstmt2 = CONCAT("UPDATE ", @var_tbl_pmonth, " SET AcctStopTime = ?, AcctSessionTime = UNIX_TIMESTAMP(?) - UNIX_TIMESTAMP(AcctStartTime), AcctStopDelay = ?, ConnectInfo_stop = '', RTPStatistics = ?, Normalized = '0' WHERE AcctSessionId = ? AND ((SipToTag = ? AND SipFromTag = ?) OR (SipToTag = ? AND SipFromTag = ?)) AND ConnectInfo_stop IS NULL AND (MediaInfo IS NULL OR MediaInfo != 'timeout') ;"); PREPARE update_rad2 FROM @updstmt2; EXECUTE update_rad2 USING @v_AcctStopTime, @v_AcctStopTime, @v_AcctStopDelay, @v_RTPStatistics, @v_AcctSessionId, @v_SipToTag, @v_SipFromTag, @v_SipFromTag, @v_SipToTag; END IF; SET @updatedrows = (SELECT ROW_COUNT()), @updstmt = null; DEALLOCATE PREPARE update_rad2; ELSE SET @updatedrows = 0; END IF; END IF; -- CLEAN UP SET @v_AcctStopTime = null, @v_AcctStopDelay = null, @v_RTPStatistics = null, @usec = null, @v_AcctSessionId = null, @v_SipToTag = null, @v_SipFromTag = null, @v_db_name = null; END $$ DELIMITER ; -- CREATE "MEDIAPROXY RECORD UPDATE" PROCEDURE DROP PROCEDURE IF EXISTS `update_raddact_record_mediaproxy`; DELIMITER $$ CREATE PROCEDURE `update_raddact_record_mediaproxy`( IN var_db_name VARCHAR(20), IN var_AcctSessionTime decimal(32,6), IN var_AcctInputOctets bigint(12), IN var_AcctOutputOctets bigint(12), IN var_MediaRelay VARCHAR(15), IN var_SipUserAgents VARCHAR(255), IN var_SipCodecs VARCHAR(255), IN var_SipApplicationType VARCHAR(255), IN var_MediaInfo VARCHAR(32), IN var_Normalized ENUM('0','1'), IN var_AcctSessionId VARCHAR(255), IN var_SipToTag VARCHAR(128), IN var_SipFromTag VARCHAR(128) ) BEGIN -- SET VARIABLES SET @var_tbl_begin = (SELECT set_radacct_table_name()), @var_prev_month = (SELECT DATE_FORMAT(DATE_ADD(CURRENT_DATE, INTERVAL -1 MONTH), '%Y%m')), @var_current_month = (SELECT DATE_FORMAT(CURRENT_DATE, '%Y%m')), @var_tbl = CONCAT(@var_tbl_begin, @var_current_month), @var_tbl_prev_month = CONCAT(@var_tbl_begin, @var_prev_month), @v_AcctSessionTime = var_AcctSessionTime, @v_AcctInputOctets = var_AcctInputOctets, @v_AcctOutputOctets = var_AcctOutputOctets, @v_MediaRelay = var_MediaRelay, @v_SipUserAgents = var_SipUserAgents, @v_SipCodecs = var_SipCodecs, @v_SipApplicationType = var_SipApplicationType, @v_MediaInfo = var_MediaInfo, @v_Normalized = var_Normalized, @v_AcctSessionId = var_AcctSessionId, @v_SipToTag = var_SipToTag, @v_SipFromTag = var_SipFromTag, @v_na = 'n/a', @v_dbname = var_db_name, @updatedrows = 0, @var_tbl_cnt1 = (SELECT COUNT(TABLE_NAME) AS TBLCNT FROM information_schema.tables WHERE TABLE_SCHEMA = @v_dbname AND TABLE_NAME = @var_tbl), @var_tbl_cnt2 = (SELECT COUNT(TABLE_NAME) AS TBLCNT FROM information_schema.tables WHERE TABLE_SCHEMA = @v_dbname AND TABLE_NAME = @var_tbl_prev_month), @proc_query = CONCAT("CALL proc_update_raddact_record_mediaproxy (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); PREPARE proc_rad_stmt FROM @proc_query; IF @var_tbl_cnt1 = 1 THEN -- FOR THE CURRENT MONTH EXECUTE proc_rad_stmt USING @var_tbl, @v_AcctSessionTime, @v_AcctInputOctets, @v_AcctOutputOctets, @v_MediaRelay, @v_SipUserAgents, @v_SipCodecs, @v_SipApplicationType, @v_MediaInfo, @v_Normalized, @v_AcctSessionId, @v_SipToTag, @v_SipFromTag, @v_dbname; END IF; IF @updatedrows = 0 AND @var_tbl_cnt2 = 1 THEN -- FOR THE PREVIOUS MONTH EXECUTE proc_rad_stmt USING @var_tbl_prev_month, @v_AcctSessionTime, @v_AcctInputOctets, @v_AcctOutputOctets, @v_MediaRelay, @v_SipUserAgents, @v_SipCodecs, @v_SipApplicationType, @v_MediaInfo, @v_Normalized, @v_AcctSessionId, @v_SipToTag, @v_SipFromTag, @v_dbname; IF @var_tbl_cnt1 = 1 AND @updatedrows = 0 THEN -- FOR THE CURRENT MONTH WITH SipToTag = 'n/a' EXECUTE proc_rad_stmt USING @var_tbl, @v_AcctSessionTime, @v_AcctInputOctets, @v_AcctOutputOctets, @v_MediaRelay, @v_SipUserAgents, @v_SipCodecs, @v_SipApplicationType, @v_MediaInfo, @v_Normalized, @v_AcctSessionId, @v_na, @v_SipFromTag, @v_dbname; IF @var_tbl_cnt2 = 1 AND @updatedrows = 0 THEN -- FOR THE PREVIOUS MONTH WITH SipToTag = 'n/a' EXECUTE proc_rad_stmt USING @var_tbl_prev_month, @v_AcctSessionTime, @v_AcctInputOctets, @v_AcctOutputOctets, @v_MediaRelay, @v_SipUserAgents, @v_SipCodecs, @v_SipApplicationType, @v_MediaInfo, @v_Normalized, @v_AcctSessionId, @v_na, @v_SipFromTag, @v_dbname; END IF; END IF; END IF; DEALLOCATE PREPARE proc_rad_stmt; -- CLEAN UP SET @var_current_month = null, @var_db_name = null, @var_tbl_begin = null, @var_tbl = null, @var_tbl_cnt = null, @var_prev_month = null, @var_tbl_prev_month = null, @v_AcctSessionTime = null, @v_AcctInputOctets = null, @v_AcctOutputOctets = null, @v_MediaRelay = null, @v_SipUserAgents = null, @v_SipCodecs = null, @v_SipApplicationType = null, @v_MediaInfo = null, @v_Normalized = null, @v_AcctSessionId = null, @v_SipFromTag = null, @v_SipToTag = null, @v_na = null, @v_dbname = null; END $$ DELIMITER ; -- CREATE SUPPORT PROCEDURE FOR "update_raddact_record_mediaproxy" DROP PROCEDURE IF EXISTS `proc_update_raddact_record_mediaproxy`; DELIMITER $$ CREATE PROCEDURE `proc_update_raddact_record_mediaproxy`( IN var_tblname VARCHAR(50), IN var_AcctSessionTime decimal(32,6), IN var_AcctInputOctets bigint(12), IN var_AcctOutputOctets bigint(12), IN var_MediaRelay VARCHAR(15), IN var_SipUserAgents VARCHAR(255), IN var_SipCodecs VARCHAR(255), IN var_SipApplicationType VARCHAR(255), IN var_MediaInfo VARCHAR(32), IN var_Normalized ENUM('0','1'), IN var_AcctSessionId VARCHAR(255), IN var_SipToTag VARCHAR(128), IN var_SipFromTag VARCHAR(128), IN var_dbname VARCHAR(20) ) BEGIN -- TABLENAME VARIABLE SET @var_tbl = var_tblname, @var_db_name = var_dbname, @var_MediaInfo = var_MediaInfo, @var_tbl_cnt = (SELECT COUNT(TABLE_NAME) AS TBLCNT FROM information_schema.tables WHERE TABLE_SCHEMA = @var_db_name AND TABLE_NAME = @var_tbl); IF @var_tbl_cnt = 0 THEN -- TABLE DOESN'T EVEN EXISTS, SO RETURN 0 SET @rcnt = (SELECT 0); ELSE IF @var_MediaInfo = 'ICE session' THEN SET @radupdstmt = CONCAT("UPDATE ", @var_tbl, " SET MediaInfo = ?, FramedIPAddress = ?, SipUserAgents = ?, SipCodecs = ?, Normalized = '0' WHERE AcctSessionId = ? AND SipToTag = ? AND SipFromTag = ?;"); PREPARE update_rad FROM @radupdstmt; SET @v_MediaInfo = var_MediaInfo, @v_MediaRelay = var_MediaRelay, @v_SipUserAgents = var_SipUserAgents, @v_SipCodecs = var_SipCodecs, @v_AcctSessionId = var_AcctSessionId, @v_SipToTag = var_SipToTag, @v_SipFromTag = var_SipFromTag; EXECUTE update_rad USING @v_MediaInfo, @v_MediaRelay, @v_SipUserAgents, @v_SipCodecs, @v_AcctSessionId, @v_SipToTag, @v_SipFromTag; SET @rcnt = (SELECT ROW_COUNT()); DEALLOCATE PREPARE update_rad; ELSE SET @radupdstmt = CONCAT("UPDATE ", @var_tbl, " SET AcctSessionTime = AcctSessionTime + IF(ConnectInfo_stop IS NULL, ?, 0), AcctStopTime = DATE_FORMAT(DATE_ADD(AcctStartTime, INTERVAL AcctSessionTime SECOND), '%Y-%m-%d %H:%i:%s.%f'), AcctInputOctets = AcctInputOctets + ?, AcctOutputOctets = AcctOutputOctets + ?, FramedIPAddress = ?, SipUserAgents = ?, SipCodecs = ?, MediaInfo = ?, Normalized = ? WHERE AcctSessionId = ? AND SipToTag = ? AND SipFromTag = ?;"); PREPARE update_rad FROM @radupdstmt; SET @v_AcctSessionTime = var_AcctSessionTime, @v_AcctInputOctets = var_AcctInputOctets, @v_AcctOutputOctets = var_AcctOutputOctets, @v_MediaRelay = var_MediaRelay, @v_SipUserAgents = var_SipUserAgents, @v_SipCodecs = var_SipCodecs, @v_MediaInfo = var_MediaInfo, @v_Normalized = var_Normalized, @v_AcctSessionId = var_AcctSessionId, @v_SipToTag = var_SipToTag, @v_SipFromTag = var_SipFromTag; EXECUTE update_rad USING @v_AcctSessionTime, @v_AcctInputOctets, @v_AcctOutputOctets, @v_MediaRelay, @v_SipUserAgents, @v_SipCodecs, @v_MediaInfo, @v_Normalized, @v_AcctSessionId, @v_SipToTag, @v_SipFromTag; SET @rcnt = (SELECT ROW_COUNT()); DEALLOCATE PREPARE update_rad; END IF; END IF; END $$ DELIMITER ; /* -- TEST PROCEDURE THAT INSERTS A RECORD CALL insert_radacct_record ( 'radius','3c3b5ff12bf2-m5udeydrjsuw@snom320-000413241247', '5af53194787eccf1', 'adi@umts.ro', 'adi@umts.ro', '83.149.75.105', '5060', '2006-12-10 12:09:19', '0', '0', '0', '0', 'sip:3333@umts.ro=3Buser=3Dphone', 'sip:adi@umts.ro', '200', 'Sip-Session', '', '', '0', '0', '200', 'Invite', 'sip:3333@vm01.dns-hosting.info', 'as5664a60b', '27qems1o2j', '31208005169', '81.23.228.147', '5060', 'sip:3333@vm01.dns-hosting.info', '', '', 'audio','sipsimple 0.11.0','' ); CALL insert_radacct_record ( 'radius','c3b5ff12bf2-m5udeydrjsuw@snom320-000413241247', '5af53194787eccf1', 'adi@umts.ro', 'adi@umts.ro', '83.149.75.105', '5060', '2009-12-14 12:09:19', '0', '0', '0', '0', 'sip:3333@umts.ro', 'sip:adi@umts.ro', '200', 'Sip-Session', '', '', '0', '0', '200', 'Invite', 'sip:test@umts.ro', 'a60bsss', 'qe222ms1o2j', '208005169', '81.23.228.147', '5060', 'sip:test@umts.ro', '', '', 'chat','Blink-0.11.1','' ); -- TEST PROCEDURE THAT UPDATES A RECORD WITH MEDIAPROXY INFORMATION CALL update_raddact_record_mediaproxy ( 'radius','3','5896','7140','snom320/5.2 + Asterisk', 'GSM', 'Audio', '', '0', 'c3b5ff12bf2-m5udeydrjsuw@snom320-000413241247', 'as5664a60b','27qems1o2j' ); -- TEST PROCEDURE THAT UPDATES A RECORD CALL update_radacct_record ( 'radius','2009-12-10 12:09:21', '0', '', 'n/a', 'c3b5ff12bf2-m5udeydrjsuw@snom320-000413241247', 'as5664a60b', '27qems1o2j' ); */ diff --git a/setup/radius/OpenSIPS/sql.conf b/setup/radius/OpenSIPS/sql.conf index 8ecf530..2efcafe 100644 --- a/setup/radius/OpenSIPS/sql.conf +++ b/setup/radius/OpenSIPS/sql.conf @@ -1,138 +1,140 @@ # # Configuration for the Freeradius SQL module, when using MySQL stored procedures # that rotate automatically tables in the format radacctYYYYMM # # It requires: # # 1. mediaproxy >=1.8.0 available from http://mediaproxy.ag-projects.com # # 2. patch to freeradius to support stored procedures available in # setup/radius/freeradius/freeradius.patch # # 3. MySQL server >= 5.0.13 # # 4. MySQL stored procedures created by Andrei Magureanu available in # setup/radius/OpenSIPS/radius_accounting.proc # # 5. If usec should be used, %S needs to be removed and it just needs to be # ''. Mysql will determine the time with now_usec # # sql { driver = "rlm_sql_mysql" server = "sipdb" login = "radius" password = "PASSWORD" radius_db = "radius" sqltrace = no sqltracefile = ${logdir}/sqltrace-%Y%m%d.log num_sql_socks = 25 connect_failure_retry_delay = 60 accounting_start_query = "\ CALL insert_radacct_record( \ 'radius', \ '%{Acct-Session-Id}', \ '%{Acct-Unique-Session-Id}', \ '%{Billing-Party}', \ '%{Billing-Party}', \ '%{SIP-Proxy-IP}', \ '%{NAS-Port}', \ FROM_UNIXTIME(%{Event-Timestamp}), \ '0', \ '0', \ '0', \ '0', \ '%{TLS-Common-Name}', \ '%{Called-Station-Id}', \ '%{Calling-Station-Id}', \ '%{Sip-Response-Code}', \ '%{Service-Type}', \ '%{ENUM-TLD}', \ '%{Framed-IP-Address}', \ UNIX_TIMESTAMP('%S') - '%{Event-Timestamp}', \ UNIX_TIMESTAMP('%S') - '%{Event-Timestamp}', \ '%{Sip-Response-Code}', \ '%{Sip-Method}', \ '%{Sip-Translated-Request-URI}', \ '%{Sip-To-Tag}', \ '%{Sip-From-Tag}', \ '%{Sip-RPId}', \ + '', \ '%{Source-IP}', \ '%{Source-Port}', \ '%{Canonical-URI}', \ '', \ '', \ '%{Sip-Application-Type}', \ '%{User-Agent}', \ '%{From-Header}' \ )" accounting_stop_query = "\ CALL update_radacct_record( \ 'radius', \ FROM_UNIXTIME(%{Event-Timestamp}), \ UNIX_TIMESTAMP('%S') - '%{Event-Timestamp}', \ '', \ '%{X-RTP-Stat}', \ '%{Acct-Session-Id}', \ '%{Sip-To-Tag}', \ '%{Sip-From-Tag}' \ )" accounting_update_query = "\ CALL update_raddact_record_mediaproxy( \ 'radius', \ '%{Acct-Session-Time}', \ '%{Acct-Input-Octets}', \ '%{Acct-Output-Octets}', \ '%{NAS-IP-Address}',\ '%{Sip-User-Agents}', \ '%{Media-Codecs}', \ '%{Sip-Applications}', \ '%{Media-Info}', \ '0', \ '%{Acct-Session-Id}', \ '%{Sip-To-Tag}', \ '%{Sip-From-Tag}' \ )" accounting_failed_query = "\ CALL insert_radacct_record( \ 'radius', \ '%{Acct-Session-Id}', \ '%{Acct-Unique-Session-Id}', \ '%{Billing-Party}', \ '%{Billing-Party}', \ '%{SIP-Proxy-IP}', \ '%{NAS-Port}', \ FROM_UNIXTIME(%{Event-Timestamp}), \ FROM_UNIXTIME(%{Event-Timestamp}), \ '0', \ '0', \ '0', \ '%{TLS-Common-Name}', \ '%{Called-Station-Id}', \ '%{Calling-Station-Id}', \ '%{Sip-Response-Code}', \ '%{Service-Type}', \ '%{ENUM-TLD}', \ '%{Framed-IP-Address}', \ UNIX_TIMESTAMP('%S') - '%{Event-Timestamp}', \ UNIX_TIMESTAMP('%S') - '%{Event-Timestamp}', \ '%{Sip-Response-Code}', \ '%{Sip-Method}', \ '%{Sip-Translated-Request-URI}', \ MD5(RAND()), \ '%{Sip-From-Tag}', \ '%{Sip-RPId}', \ + '', \ '%{Source-IP}', \ '%{Source-Port}', \ '%{Canonical-URI}', \ '', \ '', \ '%{Sip-Application-Type}', \ '%{User-Agent}', \ '%{From-Header}' \ )" }