4
* Version: $Id: rlm_counter.c,v 1.32.2.5 2003/10/04 00:20:54 phampson Exp $
4
* Version: $Id: rlm_counter.c,v 1.43 2004/02/26 19:04:28 aland Exp $
6
6
* This program is free software; you can redistribute it and/or modify
7
7
* it under the terms of the GNU General Public License as published by
20
20
* Copyright 2001 The FreeRADIUS server project
21
21
* Copyright 2001 Alan DeKok <aland@ox.org>
22
* Copyright 2001,2002 Kostas Kalevras <kkalev@noc.ntua.gr>
22
* Copyright 2001-3 Kostas Kalevras <kkalev@noc.ntua.gr>
25
25
#include "config.h"
57
57
#define UNIQUEID_MAX_LEN 32
59
static const char rcsid[] = "$Id: rlm_counter.c,v 1.32.2.5 2003/10/04 00:20:54 phampson Exp $";
59
static const char rcsid[] = "$Id: rlm_counter.c,v 1.43 2004/02/26 19:04:28 aland Exp $";
62
62
* Define a structure for our module configuration.
131
131
* See if the counter matches.
133
static int counter_cmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check,
134
VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
133
static int counter_cmp(void *instance,
135
VALUE_PAIR *request, VALUE_PAIR *check,
136
VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
136
138
rlm_counter_t *data = (rlm_counter_t *) instance;
171
174
datum time_datum;
172
175
const char *default1 = "DEFAULT1";
173
176
const char *default2 = "DEFAULT2";
175
178
DEBUG2("rlm_counter: add_defaults: Start");
177
key_datum.dptr = (const char *) default1;
180
key_datum.dptr = (char *) default1;
178
181
key_datum.dsize = strlen(default1);
179
182
time_datum.dptr = (char *) &data->reset_time;
180
183
time_datum.dsize = sizeof(time_t);
187
190
DEBUG2("rlm_counter: DEFAULT1 set to %d",(int)data->reset_time);
189
key_datum.dptr = (const char *) default2;
192
key_datum.dptr = (char *) default2;
190
193
key_datum.dsize = strlen(default2);
191
194
time_datum.dptr = (char *) &data->last_reset;
192
195
time_datum.dsize = sizeof(time_t);
242
245
unsigned int num=1;
244
247
struct tm *tm, s_tm;
248
char sCurrentTime[40], sNextTime[40];
246
250
tm = localtime_r(&timeval, &s_tm);
251
strftime(sCurrentTime, sizeof(sCurrentTime),"%Y-%m-%d %H:%M:%S",tm);
247
252
tm->tm_sec = tm->tm_min = 0;
249
254
if (data->reset == NULL)
295
DEBUG2("rlm_counter: Current Time: %d, Next reset %d",
296
(int)timeval,(int)data->reset_time);
300
strftime(sNextTime, sizeof(sNextTime),"%Y-%m-%d %H:%M:%S",tm);
301
DEBUG2("rlm_counter: Current Time: %d [%s], Next reset %d [%s]",
302
(int)timeval,sCurrentTime,(int)data->reset_time,sNextTime);
344
350
cache_size = data->cache_size;
347
* Discover the attribute number of the key.
353
* Discover the attribute number of the key.
349
355
if (data->key_name == NULL) {
350
356
radlog(L_ERR, "rlm_counter: 'key' must be set.");
361
367
data->key_attr = dattr->attr;
364
* Discover the attribute number of the counter.
370
* Discover the attribute number of the counter.
366
372
if (data->count_attribute == NULL) {
367
373
radlog(L_ERR, "rlm_counter: 'count-attribute' must be set.");
477
483
* If DEFAULT1 and DEFAULT2 do not exist (new database) we add them to the database
480
key_datum.dptr = (const char *)default1;
486
key_datum.dptr = (char *)default1;
481
487
key_datum.dsize = strlen(default1);
483
489
time_datum = gdbm_fetch(data->gdbm, key_datum);
500
506
data->reset_time = next_reset;
501
key_datum.dptr = (const char *)default2;
507
key_datum.dptr = (char *)default2;
502
508
key_datum.dsize = strlen(default2);
504
time_datum = gdbm_fetch(data->gdbm, key_datum);
510
time_datum = gdbm_fetch(data->gdbm, key_datum);
505
511
if (time_datum.dptr != NULL){
506
512
memcpy(&data->last_reset, time_datum.dptr, sizeof(time_t));
507
513
free(time_datum.dptr);
567
573
if (data->reset_time && (data->reset_time <= request->timestamp)) {
576
DEBUG("rlm_counter: Time to reset the database.");
570
577
data->last_reset = data->reset_time;
571
578
find_next_reset(data,request->timestamp);
572
579
pthread_mutex_lock(&data->mutex);
583
590
DEBUG("rlm_counter: Could not find Service-Type attribute in the request. Returning NOOP.");
584
591
return RLM_MODULE_NOOP;
586
if (proto_vp->lvalue != data->service_val){
593
if ((unsigned)proto_vp->lvalue != data->service_val){
587
594
DEBUG("rlm_counter: This Service-Type is not allowed. Returning NOOP.");
588
595
return RLM_MODULE_NOOP;
595
602
key_vp = pairfind(request->packet->vps, PW_ACCT_DELAY_TIME);
596
603
if (key_vp != NULL){
597
if (key_vp->lvalue != 0 && (request->timestamp - key_vp->lvalue) < data->last_reset){
604
if (key_vp->lvalue != 0 &&
605
(request->timestamp - key_vp->lvalue) < data->last_reset){
598
606
DEBUG("rlm_counter: This packet is too old. Returning NOOP.");
599
607
return RLM_MODULE_NOOP;
606
614
* Look for the key. User-Name is special. It means
624
632
key_datum.dptr = key_vp->strvalue;
625
633
key_datum.dsize = key_vp->length;
635
DEBUG("rlm_counter: Searching the database for key '%s'",key_vp->strvalue);
627
636
pthread_mutex_lock(&data->mutex);
628
637
count_datum = gdbm_fetch(data->gdbm, key_datum);
629
638
pthread_mutex_unlock(&data->mutex);
630
639
if (count_datum.dptr == NULL){
640
DEBUG("rlm_counter: Could not find the requested key in the database.");
631
641
counter.user_counter = 0;
632
642
if (uniqueid_vp != NULL)
633
strncpy(uniqueid_vp->strvalue,counter.uniqueid,UNIQUEID_MAX_LEN - 1);
643
strncpy(counter.uniqueid,uniqueid_vp->strvalue,UNIQUEID_MAX_LEN - 1);
635
645
memset((char *)counter.uniqueid,0,UNIQUEID_MAX_LEN);
648
DEBUG("rlm_counter: Key found.");
638
649
memcpy(&counter, count_datum.dptr, sizeof(rad_counter));
639
650
free(count_datum.dptr);
640
651
if (counter.uniqueid)
641
652
DEBUG("rlm_counter: Counter Unique ID = '%s'",counter.uniqueid);
642
if (uniqueid_vp != NULL){
643
if (counter.uniqueid != NULL &&
653
if (uniqueid_vp != NULL){
654
if (counter.uniqueid != NULL &&
644
655
strncmp(uniqueid_vp->strvalue,counter.uniqueid, UNIQUEID_MAX_LEN - 1) == 0){
645
656
DEBUG("rlm_counter: Unique IDs for user match. Droping the request.");
646
657
return RLM_MODULE_NOOP;
682
693
DEBUG("rlm_counter: User=%s, New Counter=%d.",request->username->strvalue,counter.user_counter);
683
count_datum.dptr = (rad_counter *) &counter;
694
count_datum.dptr = (char *) &counter;
684
695
count_datum.dsize = sizeof(rad_counter);
697
DEBUG("rlm_counter: Storing new value in database.");
686
698
pthread_mutex_lock(&data->mutex);
687
699
rcode = gdbm_store(data->gdbm, key_datum, count_datum, GDBM_REPLACE);
688
700
pthread_mutex_unlock(&data->mutex);
764
777
counter.user_counter = 0;
779
DEBUG("rlm_counter: Searching the database for key '%s'",key_vp->strvalue);
766
780
pthread_mutex_lock(&data->mutex);
767
781
count_datum = gdbm_fetch(data->gdbm, key_datum);
768
782
pthread_mutex_unlock(&data->mutex);
769
783
if (count_datum.dptr != NULL){
784
DEBUG("rlm_counter: Key Found.");
770
785
memcpy(&counter, count_datum.dptr, sizeof(rad_counter));
771
786
free(count_datum.dptr);
789
DEBUG("rlm_counter: Could not find the requested key in the database.");
775
792
* Check if check item > counter
794
DEBUG("rlm_counter: Check item = %d, Count = %d",check_vp->lvalue,counter.user_counter);
777
795
res=check_vp->lvalue - counter.user_counter;
797
DEBUG("rlm_counter: res is greater than zero");
779
798
if (data->count_attr == PW_ACCT_SESSION_TIME) {
781
* Do the following only if the count attribute is
800
* Do the following only if the count attribute is
782
801
* AcctSessionTime
839
858
snprintf(module_fmsg,sizeof(module_fmsg), "rlm_counter: Maximum %s usage time reached", data->reset);
840
859
module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ);
841
pairadd(&request->packet->vps, module_fmsg_vp);
860
pairadd(&request->packet->vps, module_fmsg_vp);
843
862
ret=RLM_MODULE_REJECT;