Fixes for porting to "stable" branch
[freeradius.git] / doc / rlm_sqlcounter
index 8b99e04..b170e89 100644 (file)
-       #  This module is an SQL enabled version of the counter module.
-       #  
-       #  Rather than maintaining seperate (GDBM) databases of accounting info
-       #       for each counter, this module uses the data stored in the raddacct
-       #       table by the sql modules. This module NEVER does any database 
-       #       INSERTs or UPDATEs.  It is totally dependent on the SQL module
-       #       to process Accounting packets.
-       #
-       #  The 'sqlmod_inst' parameter holds the instance of the sql module to use 
-       #       when querying the SQL database. Normally it is just "sql".
-       #       If you define more and one SQL module instance 
-       #       (usually for failover situations), you can specify which module
-       #       has access to the Accounting Data (radacct table).
-       #
-       #  The 'reset' parameter defines when the counters are all reset to
-       #       zero.  It can be hourly, daily, weekly, monthly or never.
-       #       It can also be user defined. It should be of the form:
-       #       num[hdwm] where:
-       #       h: hours, d: days, w: weeks, m: months
-       #       If the letter is ommited days will be assumed. In example:
-       #       reset = 10h (reset every 10 hours)
-       #       reset = 12  (reset every 12 days)
-       #
-       #  The 'key' parameter specifies the unique identifier for the counters
-       #       records (usually 'User-Name'). 
-       #
-       # The 'query' parameter specifies the SQL query used to get the 
-       #       current Counter value from the database. There are 3 parameters
-       #       that can be used in the query:
-       #               %k      'key' parameter
-       #               %b      unix time value of beginning of reset period 
-       #               %e      unix time value of end of reset period
-       #
-       #  The 'check-name' parameter is the name of the 'check' attribute to use to access
-       #       the counter in the 'users' file or SQL radcheck or radcheckgroup 
-       #       tables.
-       #
-       #  DEFAULT  Max-Daily-Session > 3600, Auth-Type = Reject
-       #      Reply-Message = "You've used up more than one hour today"
-       #1
-
-       sqlcounter dailycounter {
-               counter-name = Daily-Session-Time
-               check-name = Max-Daily-Session
-               sqlmod-inst = sqlcca3
-               key = User-Name
-               reset = daily
-
-               # This query properly handles calls that span from the previous reset period
-               # into the current period but involves more work for the SQL server than those below
-               query = "SELECT SUM(AcctSessionTime - GREATEST((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'"
-
-               # This query ignores calls that started in a previous reset period and 
-               # continue into into this one. But it is a little easier on the SQL server 
-               # query = "SELECT SUM(AcctSessionTime) FROM radacct WHERE UserName='%{%k}' AND AcctStartTime > FROM_UNIXTIME('%b')"
-
-               # This query is the same as above, but demonstrates an additional 
-               # counter parameter '%e' which is the timestamp for the end of the period
-               # query = "SELECT SUM(AcctSessionTime) FROM radacct WHERE UserName='%{%k}' AND AcctStartTime BETWEEN FROM_UNIXTIME('%b') AND FROM_UNIXTIME('%e')"               
-       }
+rlm_sqlcounter installation and running guide
+by Ram Narula ram@princess1.net
+Internet for Education (Thailand)
+
+*) Pre-requisites:
+Make sure to have configured radiusd with rlm_sqlcounter
+installed
+
+> make clean
+> ./configure --with-experimental-modules
+> make
+> make install
 
-       sqlcounter monthlycounter {
-               counter-name = Monthly-Session-Time
-               check-name = Max-Monthly-Session
-               sqlmod-inst = sqlcca3
-               key = User-Name
-               reset = monthly
+Make sure to have radiusd running properly under sql
+and there must be a "sql" entry under accounting{ } section
+of radiusd.conf
 
-               # This query properly handles calls that span from the previous reset period
-               # into the current period but involves more work for the SQL server than those below
-               query = "SELECT SUM(AcctSessionTime - GREATEST((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'"
+*) Configuration:
 
-               # This query ignores calls that started in a previous reset period and 
-               # continue into into this one. But it is a little easier on the SQL server 
-               # query = "SELECT SUM(AcctSessionTime) FROM radacct WHERE UserName='%{%k}' AND AcctStartTime > FROM_UNIXTIME('%b')"
+[1] Create a text file called sqlcounter.conf in the same
+directory where radiusd.conf resides (usually /usr/local/etc/raddb)
+with the following content (for mysql):
+
+#-----#
+sqlcounter noresetcounter {
+                counter-name = Max-All-Session-Time
+                check-name = Max-All-Session
+                reply-name = Session-Timeout
+                sqlmod-inst = sql
+                key = User-Name
+                reset = never
+
+                query = "SELECT SUM(AcctSessionTime) FROM radacct WHERE UserName='%{%k}'"
+
+        }
+
+
+sqlcounter dailycounter {
+                driver = "rlm_sqlcounter"
+                counter-name = Daily-Session-Time
+                check-name = Max-Daily-Session
+                reply-name = Session-Timeout
+                sqlmod-inst = sqlcca3
+                key = User-Name
+                reset = daily
+
+                query = "SELECT SUM(AcctSessionTime - GREATEST((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'"
+
+        }
+
+sqlcounter monthlycounter {
+                counter-name = Monthly-Session-Time
+                check-name = Max-Monthly-Session
+                reply-name = Session-Timeout
+                sqlmod-inst = sqlcca3
+                key = User-Name
+                reset = monthly
+
+                query = "SELECT SUM(AcctSessionTime - GREATEST((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'"
 
-               # This query is the same as above, but demonstrates an additional 
-               # counter parameter '%e' which is the timestamp for the end of the period
-               # query = "SELECT SUM(AcctSessionTime) FROM radacct WHERE UserName='%{%k}' AND AcctStartTime BETWEEN FROM_UNIXTIME('%b') AND FROM_UNIXTIME('%e')"               
        }
 
+#-----#
+
+The respective lines for postgresql are:
+
+query = "SELECT SUM(AcctSessionTime) FROM radacct WHERE UserName='%{%k}'"
+query = "SELECT SUM(AcctSessionTime - GREATER((%b - AcctStartTime::ABSTIME::INT4), 0)) FROM radacct WHERE UserName='%{%k}' AND AcctStartTime::ABSTIME::INT4 + AcctSessionTime > '%b'"
+query = "SELECT SUM(AcctSessionTime - GREATER((%b - AcctStartTime::ABSTIME::INT4), 0)) FROM radacct WHERE UserName='%{%k}' AND AcctStartTime::ABSTIME::INT4 + AcctSessionTime > '%b'"
+
+If you are running postgres 7.x, you may not have a GREATER function.
+
+An example of one is:
+
+CREATE OR REPLACE FUNCTION "greater"(integer, integer) RETURNS integer AS '
+DECLARE
+  res INTEGER;
+  one INTEGER := 0;
+  two INTEGER := 0;
+BEGIN
+  one = $1;
+  two = $2;
+  IF one IS NULL THEN
+    one = 0;
+  END IF;
+  IF two IS NULL THEN
+    two = 0;
+  END IF;
+  IF one > two THEN
+    res := one;
+  ELSE
+    res := two;
+  END IF;
+  RETURN res;
+END;
+' LANGUAGE 'plpgsql';
+
+[2] Include the above file to radiusd.conf by adding a line in
+modules{ } section
+
+modules {
+
+$INCLUDE  ${confdir}/sqlcounter.conf
+
+...some other entries here...
+
+[3] Make sure to have the sqlcounter names under authorize section
+like the followings:
 
-# Authorization. First preprocess (hints and huntgroups files),
-# then realms, and finally look in the "users" file.
-# The order of the realm modules will determine the order that
-# we try to find a matching realm.
-# Make *sure* that 'preprocess' comes before any realm if you 
-# need to setup hints for the remote radius server
 authorize {
-       preprocess
-#      attr_filter
-#      eap
-       suffix
-       files
-        group {
-                sql1 {
-                        fail     = 1
-                        notfound = return
-                        noop     = 2
-                        ok       = return
-                        updated  = 3
-                        reject   = return
-                        userlock = 4
-                        invalid  = 5
-                        handled  = 6
-                }
-                sql2 {
-                        fail     = 1
-                        notfound = return
-                        noop     = 2
-                        ok       = return
-                        updated  = 3
-                        reject   = return
-                        userlock = 4
-                        invalid  = 5
-                        handled  = 6
-                }
-        }
-       dailycounter
-       monthlycounter
-#      mschap
+...some entries here...
+...some entries here...
+...some entries here...
+...some entries here...
+
+noresetcounter
+dailycounter
+monthlycounter
 }
 
+noresetcounter: the counter that never resets, can be used
+for real session-time cumulation 
 
-# Authentication.
-#
-# This section lists which modules are available for authentication.
-# Note that it does NOT mean 'try each module in order'.  It means
-# that you have to have a module from the 'authorize' section add
-# a configuration attribute 'Auth-Type := FOO'.  That authentication type
-# is then used to pick the apropriate module from the list below.
-authenticate {
-#      pam
-#      unix
-#      ldap
-       mschap
-#      pap
-#      eap
-}
+dailycounter: the counter that resets everyday, can be used
+for limiting daily access time (eg. 3 hours a day)
 
+monthlycounter: the counter that resets monthly, can be used for
+limiting monthly access time (eg. 50 hours per month)
 
-# Pre-accounting. Look for proxy realm in order of realms, then 
-# acct_users file, then preprocess (hints file).
-preacct {
-       suffix
-       files
-       preprocess
-}
+You can make your own names and directives for resetting the counter
+by reading the sample sqlcounter configuration in
+raddb/experimental.conf
 
 
-# Accounting. Log to detail file, and to the radwtmp file, and maintain
-# radutmp.
-accounting {
-       acct_unique
-       detail
-       sqlcca1
-#      counter
-#      unix
-       radutmp
-#      sradutmp
-}
 
+*) Implementation:
+
+Add sqlcounter names to be used into radcheck or radgroupcheck
+table appropriately for sql. For users file just follow the
+example below.
+
+Note: The users in the example below must be able to login
+normally as the example will only show how to apply sqlcounter 
+counters.
+
+Scenarios
+[1] username test0001 have total time limit of 15 hours
+(user can login as many times as needed but can be online for 
+total time of 15 hours which is 54000 seconds)
+If using normal users file authenication the entry can look like:
+
+test0001  Max-All-Session := 54000, User-Password == "blah"
+          Service-Type = Framed-User,
+          Framed-Protocol = PPP
+
+or for sql make sure to have Max-All-Session entry under either
+radcheck or radgroup check table:
+> INSERT into radcheck VALUES ('','test0001','Max-All-Session','54000',':=');
+
+[2] username test0002 have total time limit of 3 hours a day
+
+test0002  Max-Daily-Session := 10800, User-Password == "blah"
+          Service-Type = Framed-User,
+          Framed-Protocol = PPP
+or in sql:
+> INSERT into radcheck VALUES ('','test0002','Max-Daily-Session','10800',':=');
+
+
+[3] username test0003 have total time limit of 90 hours a month
+
+test0003  Max-Monthly-Session := 324000, User-Password == "blah"
+          Service-Type = Framed-User,
+          Framed-Protocol = PPP
+in sql:
+> INSERT into radcheck VALUES ('','test0003','Max-Monthly-Session','10800',':=');
+
+
+Note that Max-All-Session, Max-Daily-Session and Max-Monthly-Session are
+definied in sqlcounter.conf
+
+VERY IMPORTANT:
+Accounting must be done via sql or this will not work. 
 
-# Session database, used for checking Simultaneous-Use. The radutmp module
-# handles this
-session {
-       radutmp
-}