From 229d46c9f36e178a773903b34c2a953fbdf37c3e Mon Sep 17 00:00:00 2001 From: Robert Anderson <randerson@lbsd.net> Date: Fri, 13 Mar 2009 07:31:07 +0000 Subject: [PATCH] Preliminary support for capping users --- .../modules/features/mod_feature_capping.pm | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 smradius/modules/features/mod_feature_capping.pm diff --git a/smradius/modules/features/mod_feature_capping.pm b/smradius/modules/features/mod_feature_capping.pm new file mode 100644 index 00000000..8d4cc686 --- /dev/null +++ b/smradius/modules/features/mod_feature_capping.pm @@ -0,0 +1,174 @@ +# Capping support +# +# Copyright (C) 2008, 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 mod_feature_capping; + +use strict; +use warnings; + +# Modules we need +use smradius::constants; +use smradius::logging; +use smradius::util; + + +# Exporter stuff +require Exporter; +our (@ISA,@EXPORT,@EXPORT_OK); +@ISA = qw(Exporter); +@EXPORT = qw( +); +@EXPORT_OK = qw( +); + + + +# Plugin info +our $pluginInfo = { + Name => "User Capping Feature", + Init => \&init, + + # Authentication hook + 'Feature_Post-Authentication_hook' => \&post_auth_hook, + + # Accounting hook + 'Feature_Post-Accounting_hook' => \&post_acct_hook, +}; + + +# Some constants +my $TRAFFIC_LIMIT_KEY = 'SMRadius-Capping-Traffic-Limit'; +my $TIME_LIMIT_KEY = 'SMRadius-Capping-Time-Limit'; + + +## @internal +# Initialize module +sub init +{ + my $server = shift; +} + + +## @post_auth_hook($server,$user,$packet) +# Post authentication hook +# +# @param server Server object +# @param user User data +# @param packet Radius packet +# +# @return Result +sub post_auth_hook +{ + my ($server,$user,$packet) = @_; + + $server->log(LOG_DEBUG,"[MOD_FEATURE_CAPPING] POST AUTH HOOK"); + + my ($trafficLimit,$timeLimit); + + # Compare SMRadius-Capping-Time-Limit + if (defined($user->{'Attributes'}->{$TIME_LIMIT_KEY})) { + $server->log(LOG_DEBUG,"[MOD_FEATURE_CAPPING] '".$TIME_LIMIT_KEY."' is defined"); + # Operator: := + if (defined($user->{'Attributes'}->{$TIME_LIMIT_KEY}->{':='})) { + # Is it a number? + if ($user->{'Attributes'}->{$TIME_LIMIT_KEY}->{':='}->{'Value'} =~ /^[0-9]+$/) { + $timeLimit = $user->{'Attributes'}->{$TIME_LIMIT_KEY}; + } else { + $server->log(LOG_NOTICE,"[MOD_FEATURE_CAPPING] '".$user->{'Attributes'}->{$TIME_LIMIT_KEY}->{':='}->{'Value'}."' is NOT a numeric value"); + } + } else { + $server->log(LOG_NOTICE,"[MOD_FEATURE_CAPPING] No valid operators for attribute '".$user->{'Attributes'}->{$TIME_LIMIT_KEY}."'"); + } + } + + + # Compare SMRadius-Capping-Traffic-Limit + if (defined($user->{'Attributes'}->{$TRAFFIC_LIMIT_KEY})) { + $server->log(LOG_DEBUG,"[MOD_FEATURE_CAPPING] '".$TRAFFIC_LIMIT_KEY."' is defined"); + # Operator: += + if (defined($user->{'Attributes'}->{$TRAFFIC_LIMIT_KEY}->{':='})) { + # Is it a number? + if ($user->{'Attributes'}->{$TRAFFIC_LIMIT_KEY}->{':='}->{'Value'} =~ /^[0-9]+$/) { + $trafficLimit = $user->{'Attributes'}->{$TRAFFIC_LIMIT_KEY}; + } else { + $server->log(LOG_NOTICE,"[MOD_FEATURE_CAPPING] '".$user->{'Attributes'}->{$TRAFFIC_LIMIT_KEY}->{':='}->{'Value'}."' is NOT a numeric value"); + } + } else { + $server->log(LOG_NOTICE,"[MOD_FEATURE_CAPPING] No valid operators for attribute '".$user->{'Attributes'}->{$TRAFFIC_LIMIT_KEY}."'"); + } + } + + # Check if we need to get the users' usage + my $accountingUsage; + if (defined($timeLimit) || defined($trafficLimit)) { + # Loop with plugins to find anyting supporting getting of usage + foreach my $module (@{$server->{'plugins'}}) { + # Do we have the correct plugin? + if ($module->{'Accounting_getUsage'}) { + $server->log(LOG_INFO,"[MOD_FEATURE_CAPPING] Found plugin: '".$module->{'Name'}."'"); + # Fetch users session time & bandwidth used + my $res = $module->{'Accounting_getUsage'}($server,$user,$packet); + if (!defined($res)) { + $server->log(LOG_ERR,"[MOD_FEATURE_CAPPING] No usage data found for user '".$packet->attr('User-Name')."'"); + return MOD_RES_SKIP; + } + + $accountingUsage = $res; + } + } + } + + # Check values against limits + if (defined($timeLimit)) { + if ($accountingUsage->{'TotalTimeUsage'} >= $timeLimit->{':='}->{'Value'}) { + $server->log(LOG_DEBUG,"[MOD_FEATURE_CAPPING] Usage exceeds ".$timeLimit->{':='}->{'Value'}.", returning [NACK]"); + # Exceeding maximum, must be disconnected + return MOD_RES_NACK; + } + } + if (defined($trafficLimit)) { + if ($accountingUsage->{'TotalDataUsage'} >= $trafficLimit->{':='}->{'Value'}) { + $server->log(LOG_DEBUG,"[MOD_FEATURE_CAPPING] Usage exceeds ".$trafficLimit->{':='}->{'Value'}.", returning [NACK]"); + # Exceeding maximum, must be disconnected + return MOD_RES_NACK; + } + } + + return MOD_RES_ACK; +} + + +## @post_acct_hook($server,$user,$packet) +# Post authentication hook +# +# @param server Server object +# @param user User data +# @param packet Radius packet +# +# @return Result +sub post_acct_hook +{ + my ($server,$user,$packet) = @_; + + $server->log(LOG_DEBUG,"[MOD_FEATURE_CAPPING] POST ACCT HOOK"); + + return MOD_RES_SKIP; +} + + +1; -- GitLab