diff --git a/database/users-accounting-summary.tsql b/database/users-accounting-summary.tsql new file mode 100644 index 0000000000000000000000000000000000000000..5fcca4209fb98affa311d1f416acfc613ee01b30 --- /dev/null +++ b/database/users-accounting-summary.tsql @@ -0,0 +1,4 @@ +ALTER TABLE @TP@users ADD COLUMN PeriodKey VARCHAR(255); +ALTER TABLE @TP@users ADD COLUMN TotalTraffic @INT_UNSIGNED@; +ALTER TABLE @TP@users ADD COLUMN TotalUptime @INT_UNSIGNED@; +ALTER TABLE @TP@users ADD COLUMN NASIdentifier VARCHAR(255); diff --git a/smradius/modules/features/mod_feature_update_user_stats_sql.pm b/smradius/modules/features/mod_feature_update_user_stats_sql.pm new file mode 100644 index 0000000000000000000000000000000000000000..d6f6a70fcd5f692154e1c5fed92d2f22cce76f55 --- /dev/null +++ b/smradius/modules/features/mod_feature_update_user_stats_sql.pm @@ -0,0 +1,159 @@ +# Support for updating of user stats +# Copyright (C) 2007-2011, AllWorldIT +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +package smradius::modules::features::mod_feature_update_user_stats_sql; + +use strict; +use warnings; + +# Modules we need +use smradius::constants; +use awitpt::db::dblayer; +use smradius::logging; +use smradius::util; +use smradius::modules::accounting::mod_accounting_sql; + +# Exporter stuff +require Exporter; +our (@ISA,@EXPORT,@EXPORT_OK); +@ISA = qw(Exporter); +@EXPORT = qw( +); +@EXPORT_OK = qw( +); + + + +# Plugin info +our $pluginInfo = { + Name => "Update User Stats", + Init => \&init, + + # Accounting hook + 'Feature_Post-Accounting_hook' => \&updateUserStats +}; + + +# Module config +my $config; + + +## @internal +# Initialize module +sub init +{ + my $server = shift; + my $scfg = $server->{'inifile'}; + + + # Enable support for database + $server->log(LOG_NOTICE,"[MOD_FEATURE_UPDATE_USER_STATS_SQL] Enabling database support"); + if (!$server->{'smradius'}->{'database'}->{'enabled'}) { + $server->log(LOG_NOTICE,"[MOD_FEATURE_UPDATE_USER_STATS_SQL] Enabling database support."); + $server->{'smradius'}->{'database'}->{'enabled'} = 1; + } + + # Default configs... + $config->{'update_user_stats_query'} = ' + UPDATE + @TP@users + SET + PeriodKey = %{query.PeriodKey}, + TotalTraffic = %{query.TotalTraffic}, + TotalUptime = %{query.TotalUptime}, + NASIdentifier = %{request.NAS-Identifier} + WHERE + Username = %{request.User-Name} + '; + + # Setup SQL queries + if (defined($scfg->{'mod_feature_update_user_stats_sql'})) { + # Pull in queries + if (defined($scfg->{'mod_feature_update_user_stats_sql'}->{'update_user_stats_query'}) && + $scfg->{'mod_feature_update_user_stats_sql'}->{'update_user_stats_query'} ne "") { + if (ref($scfg->{'mod_feature_update_user_stats_sql'}->{'update_user_stats_query'}) eq "ARRAY") { + $config->{'update_user_stats_query'} = join(' ', + @{$scfg->{'mod_feature_update_user_stats_sql'}->{'update_user_stats_query'}}); + } else { + $config->{'update_user_stats_query'} = $scfg->{'mod_feature_update_user_stats_sql'}->{'update_user_stats_query'}; + } + } + } +} + + +## @updateUserStats($server,$user,$packet) +# Post authentication hook +# +# @param server Server object +# @param user User data +# @param packet Radius packet +# +# @return Result +sub updateUserStats +{ + my ($server,$user,$packet) = @_; + + # Build template + my $template; + foreach my $attr ($packet->attributes) { + $template->{'request'}->{$attr} = $packet->rawattr($attr) + } + $template->{'user'} = $user; + + # Current PeriodKey + my $now = DateTime->now->set_time_zone($server->{'smradius'}->{'event_timezone'}); + $template->{'query'}->{'PeriodKey'} = $now->strftime("%Y-%m"); + + # Loop with plugins to find anything supporting getting of usage + my $accountingUsage; + foreach my $module (@{$server->{'module_list'}}) { + # Do we have the correct plugin? + if ($module->{'Accounting_getUsage'}) { + $server->log(LOG_INFO,"[MOD_FEATURE_UPDATE_USER_STATS_SQL] Found plugin: '".$module->{'Name'}."'"); + # Fetch users session uptime & bandwidth used + my $res = $module->{'Accounting_getUsage'}($server,$user,$packet); + if (!defined($res)) { + $server->log(LOG_ERR,"[MOD_FEATURE_UPDATE_USER_STATS_SQL] No usage data found for user '".$packet->attr('User-Name')."'"); + return MOD_RES_SKIP; + } + + $accountingUsage = $res; + } + } + + # Add to our template hash + $template->{'query'}->{'TotalTraffic'} = $accountingUsage->{'TotalDataUsage'}; + $template->{'query'}->{'TotalUptime'} = $accountingUsage->{'TotalSessionTime'}; + + # Replace template entries + my (@dbDoParams) = templateReplace($config->{'update_user_stats_query'},$template); + + # Perform query + my $sth = DBDo(@dbDoParams); + if (!$sth) { + $server->log(LOG_ERR,"[MOD_FEATURE_UPDATE_USER_STATS_SQL] Database query failed: ".awitpt::db::dblayer::Error()); + return; + } + + return MOD_RES_ACK; +} + + + +1; +# vim: ts=4 diff --git a/smradiusd.conf b/smradiusd.conf index e84c263e7485ffcb75600617d857b0244fa86dd6..cba7d226424e43a0720f152ab206fbc023340107 100644 --- a/smradiusd.conf +++ b/smradiusd.conf @@ -156,6 +156,7 @@ EOT [features] modules=<<EOT mod_feature_capping +mod_feature_update_user_stats_sql EOT @@ -441,5 +442,17 @@ userdb_get_user_attributes_query=<<EOT EOT +# MOD_FEATURE_UPDATE_USER_STATS_SQL +[mod_feature_update_user_stats_sql] - +update_user_stats_query=<<EOT + UPDATE + @TP@users + SET + PeriodKey = %{query.PeriodKey}, + TotalTraffic = %{query.TotalTraffic}, + TotalUptime = %{query.TotalUptime}, + NASIdentifier = %{request.NAS-Identifier} + WHERE + Username = %{request.User-Name} +EOT