sqlcounter returning wrong value?

Venkatesh K kaevee at gmail.com
Thu Nov 13 10:21:53 CET 2008


Hi Liran,

here is the patch. I have done some initial testing.

--------------------------------------------------------------------------------------------------------------------
--- freeradius-1.1.7.orig/src/modules/rlm_sqlcounter/rlm_sqlcounter.c	2008-11-13
11:21:14.000000000 +0530
+++ freeradius-1.1.7/src/modules/rlm_sqlcounter/rlm_sqlcounter.c	2008-11-13
14:35:58.000000000 +0530
@@ -72,6 +72,8 @@
 	char *sqlmod_inst;	/* instance of SQL module to use, usually just 'sql' */
 	char *query;		/* SQL query to retrieve current session time */
 	char *reset;  		/* daily, weekly, monthly, never or user defined */
+	char *counter_type; /* Type of counter (data / time) */
+	char *check_unit;   /* Unit of Check Value in Octets/KibiOctets/MibiOctets */
 	char *allowed_chars;	/* safe characters list for SQL queries */
 	time_t reset_time;
 	time_t last_reset;
@@ -96,6 +98,8 @@
   { "key", PW_TYPE_STRING_PTR, offsetof(rlm_sqlcounter_t,key_name),
NULL, NULL },
   { "sqlmod-inst", PW_TYPE_STRING_PTR,
offsetof(rlm_sqlcounter_t,sqlmod_inst), NULL, NULL },
   { "query", PW_TYPE_STRING_PTR, offsetof(rlm_sqlcounter_t,query),
NULL, NULL },
+  { "counter-type", PW_TYPE_STRING_PTR,
offsetof(rlm_sqlcounter_t,counter_type), NULL, NULL },
+  { "check-unit", PW_TYPE_STRING_PTR,
offsetof(rlm_sqlcounter_t,check_unit), NULL, NULL },
   { "reset", PW_TYPE_STRING_PTR, offsetof(rlm_sqlcounter_t,reset),
NULL,  NULL },
   { "safe-characters", PW_TYPE_STRING_PTR,
offsetof(rlm_sqlcounter_t,allowed_chars), NULL,
"@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_:
/"},
   { NULL, -1, 0, NULL, NULL }
@@ -587,7 +591,7 @@
 	rlm_sqlcounter_t *data = (rlm_sqlcounter_t *) instance;
 	int ret=RLM_MODULE_NOOP;
 	int counter=0;
-	int res=0;
+	uint32_t res=0;
 	DICT_ATTR *dattr;
 	VALUE_PAIR *key_vp, *check_vp;
 	VALUE_PAIR *reply_item;
@@ -612,7 +616,6 @@
 		find_next_reset(data,request->timestamp);
 	}

-
 	/*
 	 *      Look for the key.  User-Name is special.  It means
 	 *      The REAL username, after stripping.
@@ -658,6 +661,25 @@
 	res=check_vp->lvalue - counter;
 	if (res > 0) {
 		DEBUG2("rlm_sqlcounter: (Check item - counter) is greater than zero");
+
+		if(data->check_unit) {
+			if(strcasecmp(data->check_unit,"KibiOctets")==0) {
+				if(res >= 4194303) {
+					res = 4294967295;
+				} else {
+					res = res * 1024;
+				}
+			} else if(strcasecmp(data->check_unit,"MibiOctets")==0) {
+				if(res >= 4095) {
+					res = 4294967295;
+				} else {
+					res = res * 1024 * 1024;
+				}
+			}
+		}
+
+		DEBUG2("rlm_sqlcounter: Post processing result=%u", res);
+
 		/*
 		 *	We are assuming that simultaneous-use=1. But
 		 *	even if that does not happen then our user
@@ -675,10 +697,17 @@
 		 *	limit, so that the user will not need to
 		 *	login again
 		 */
-		if (data->reset_time && (
-			res >= (data->reset_time - request->timestamp))) {
-			res = data->reset_time - request->timestamp;
-			res += check_vp->lvalue;
+
+		/*
+		 * While counting data transfer, We don't have to add the next limit.
+		 *
+		 */
+		if((data->counter_type) && (strcmp(data->counter_type,"time")==0)) {
+			if (data->reset_time && (
+				res >= (data->reset_time - request->timestamp))) {
+				res = data->reset_time - request->timestamp;
+				res += check_vp->lvalue;
+			}
 		}

 		if ((reply_item = pairfind(request->reply->vps, data->reply_attr)) != NULL) {
@@ -695,9 +724,9 @@

 		ret=RLM_MODULE_OK;

-		DEBUG2("rlm_sqlcounter: Authorized user %s, check_item=%d, counter=%d",
+		DEBUG2("rlm_sqlcounter: Authorized user %s, check_item=%u, counter=%d",
 				key_vp->strvalue,check_vp->lvalue,counter);
-		DEBUG2("rlm_sqlcounter: Sent Reply-Item for user %s, Type=%s, value=%d",
+		DEBUG2("rlm_sqlcounter: Sent Reply-Item for user %s, Type=%s, value=%u",
 				key_vp->strvalue,data->reply_name,reply_item->lvalue);
 	}
 	else{
---------------------------------------------------------------------------------------------

Here is a sample sqlcounter.conf

----------------------------------------------------------------------------------------------
sqlcounter noresetBytecounter {
            counter-name = Total-Max-Octets
            check-name = Max-Octets
            reply-name = ChilliSpot-Max-Total-Octets
            sqlmod-inst = sql
            key = User-Name
            reset = never
            counter-type = data
            check-unit = KibiOctets
            query = "SELECT
(SUM(AcctInputOctets)+SUM(AcctOutputOctets))/1024 FROM radacct WHERE
UserName='%{%k}'"
}
-------------------------------------------------------------------------------------------------

As you can see, you need to make changes to the units of check-item
value stored in DB. You can use KibiOctets, MibiOctets in DB and set
the sqlcounter.conf file accordingly. Even if you used KibiOctets or
MibiOctets in DB, the replies will always be sent in Octets and
maximum is limited to 4G.

Regards,

Venkatesh K



On Wed, Nov 12, 2008 at 9:11 PM, Venkatesh K <kaevee at gmail.com> wrote:
> Hi,
>
> On Wed, Nov 12, 2008 at 2:06 AM, liran tal <liransgarage at gmail.com> wrote:
>>
>> Waiting for that traffic limitation patch, Venkatesh.
>> Thanks.
>
> I am sorry. I had few busy days this week. You can expect a patch tomorrow.
>
>>
>> On Sun, Nov 9, 2008 at 6:00 AM, Venkatesh K <kaevee at gmail.com> wrote:
>>>
>>> Hi Liran,
>>>
>>> On Sun, Nov 9, 2008 at 4:16 AM, liran tal <liransgarage at gmail.com> wrote:
>>> > Hey Venkatesh,
>>> >
>>> > On Fri, Oct 31, 2008 at 2:26 AM, Venkatesh K <kaevee at gmail.com> wrote:
>>> >>
>>> >> 2008/10/31  <tnt at kalik.net>:
>>> >> > It does make sense. rlm_sqlcounterworks like this toward the time of
>>> >> > the
>>> >> > reset: lets say you have an hour left, your limit is 20 hours and you
>>> >> > have signed in 15 minutes before counter reset time.  When code
>>> >> > calculates that you can be online at reset time it doesn't return
>>> >> > your
>>> >> > allowance (1 hour) but adds the limit for the next conting period (20
>>> >> > hours) to the remaining time (15 minutes) and returns that value (20
>>> >> > hours and 15 minutes). Reasoning is that your session shouldn't be
>>> >> > discontinued after an hour becouse 15 minutes into the session new
>>> >> > limit
>>> >> > should come into force (and session limit can't be changed during the
>>> >> > session).
>>> >> >
>>> >> > In your case there is about 2,000,000 left on the counter but only a
>>> >> > few
>>> >> > thousand seconds left to the end of the reset period, so code will
>>> >> > add
>>> >> > those few thousands to the next period limit (26,000,000) and return
>>> >> > that value. Code doesn't "know" are you counting data or time as
>>> >> > there is  no such configuration item.
>>> >> >
>>> >> > Venkatesh had posted the patch that switches off this peace of code
>>> >> > for
>>> >> > data counters by introducing that configuration item. You should try
>>> >> > it.
>>> >>
>>> >> rlm_sqlcounter has one more limitation. In version 1.1.7, the maximum
>>> >> counter value was limited to <2G whereas in 2.1.1 it seems to be <4G.
>>> >> This imposes an artificial limitation of maximum of 4GB of downloads.
>>> >> I had a workaround where I patched rlm_sqlcounter to limit the per
>>> >> session downloads to 4GB if allowed usage exceeds 4GB.
>>> >>
>>> >> Except this issue, I think, with the patch I posted earlier, one
>>> >> should be fine with rlm_sqlcounter. If someone needs a patch to work
>>> >> around the 2GB/4GB limit, I will post the patch.
>>> >
>>> >
>>> > Sorry for the late reply.
>>> > I applied your patch and now data counters work as expected with a minor
>>> > exception, the 2Gb limit
>>> > as you have stated previously. Possibly you could also post the patch
>>> > for
>>> > the 2Gb/4Gb limit?
>>> > I'm hoping it's compatible with FR 1.1.7 as well.
>>> >
>>>
>>> It is ok. I am happy to know it works for you. I will email you a
>>> patch for 1.1.7 in couple of days. The patch is going to impose
>>> certain limitations on you. The maximum return value should be less
>>> than unsigned integer(32bit). The maximum reply value for data will be
>>> limited to 4GB even if actual value is more than 4GB. So, there will
>>> be a per session limit of 4GB though user is authorized to transfer
>>> more data.
>>>
>>> Regards,
>>>
>>> Venkatesh. K
>>> -
>>> List info/subscribe/unsubscribe? See
>>> http://www.freeradius.org/list/users.html
>>
>>
>> -
>> List info/subscribe/unsubscribe? See
>> http://www.freeradius.org/list/users.html
>>
>
> Regards,
>
> --
> Venkatesh. K
>



-- 
Venkatesh. K



More information about the Freeradius-Users mailing list