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@gmail.com> wrote:
Hi,
On Wed, Nov 12, 2008 at 2:06 AM, liran tal <liransgarage@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@gmail.com> wrote:
Hi Liran,
On Sun, Nov 9, 2008 at 4:16 AM, liran tal <liransgarage@gmail.com> wrote:
Hey Venkatesh,
On Fri, Oct 31, 2008 at 2:26 AM, Venkatesh K <kaevee@gmail.com> wrote:
2008/10/31 <tnt@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