* - Fail if we don't find nas port information
* Oct 2002, Kostas Kalevras <kkalev@noc.ntua.gr>
* - Do a memset(0) on the key.nas before doing searches. Nusty bug
+ * Jul 2003, Kostas Kalevras <kkalev@noc.ntua.gr>
+ * - Make Multilink work this time
+ * - Instead of locking file operations, lock transactions. That means we only keep
+ * one big transaction lock instead of per file locks (mutexes).
*/
#include "config.h"
int override;
GDBM_FILE gdbm;
GDBM_FILE ip;
- pthread_mutex_t session_mutex;
- pthread_mutex_t ip_mutex;
+ pthread_mutex_t op_mutex;
} rlm_ippool_t;
typedef struct ippool_info {
pool_name = cf_section_name2(conf);
if (pool_name != NULL)
data->name = strdup(pool_name);
- pthread_mutex_init(&data->session_mutex, NULL);
- pthread_mutex_init(&data->ip_mutex, NULL);
+ pthread_mutex_init(&data->op_mutex, NULL);
*instance = data;
break;
default:
/* We don't care about any other accounting packet */
+ DEBUG("rlm_ippool: This is not an Accounting-Stop. Return NOOP.");
return RLM_MODULE_NOOP;
}
key_datum.dptr = (char *) &key;
key_datum.dsize = sizeof(ippool_key);
- pthread_mutex_lock(&data->session_mutex);
+ pthread_mutex_lock(&data->op_mutex);
data_datum = gdbm_fetch(data->gdbm, key_datum);
- pthread_mutex_unlock(&data->session_mutex);
if (data_datum.dptr != NULL){
/*
data_datum.dptr = (char *) &entry;
data_datum.dsize = sizeof(ippool_info);
- pthread_mutex_lock(&data->session_mutex);
rcode = gdbm_store(data->gdbm, key_datum, data_datum, GDBM_REPLACE);
- pthread_mutex_unlock(&data->session_mutex);
if (rcode < 0) {
radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",
data->session_db, gdbm_strerror(gdbm_errno));
+ pthread_mutex_unlock(&data->op_mutex);
return RLM_MODULE_FAIL;
}
*/
key_datum.dptr = (char *) &entry.ipaddr;
key_datum.dsize = sizeof(uint32_t);
- pthread_mutex_lock(&data->ip_mutex);
data_datum = gdbm_fetch(data->ip, key_datum);
- pthread_mutex_unlock(&data->ip_mutex);
if (data_datum.dptr != NULL){
memcpy(&num, data_datum.dptr, sizeof(int));
free(data_datum.dptr);
DEBUG("rlm_ippool: num: %d",num);
data_datum.dptr = (char *) #
data_datum.dsize = sizeof(int);
- pthread_mutex_lock(&data->ip_mutex);
rcode = gdbm_store(data->ip, key_datum, data_datum, GDBM_REPLACE);
- pthread_mutex_unlock(&data->ip_mutex);
if (rcode < 0) {
radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",
data->ip_index, gdbm_strerror(gdbm_errno));
+ pthread_mutex_unlock(&data->op_mutex);
return RLM_MODULE_FAIL;
}
}
else
DEBUG("rlm_ippool: Entry not found");
+ pthread_mutex_unlock(&data->op_mutex);
+
return RLM_MODULE_OK;
}
if ((vp = pairfind(request->packet->vps, PW_NAS_IDENTIFIER)) != NULL)
strncpy(nas, vp->strvalue, MAX_NAS_NAME_SIZE - 1);
else{
- DEBUG("rlm_ippool: Could not find nas information.");
+ DEBUG("rlm_ippool: Could not find nas information. Return NOOP.");
return RLM_MODULE_NOOP;
}
}
if ((vp = pairfind(request->packet->vps, PW_NAS_PORT)) != NULL)
port = vp->lvalue;
else{
- DEBUG("rlm_ippool: Could not find port information.");
+ DEBUG("rlm_ippool: Could not find nas port information. Return NOOP.");
return RLM_MODULE_NOOP;
}
key_datum.dptr = (char *) &key;
key_datum.dsize = sizeof(ippool_key);
- pthread_mutex_lock(&data->session_mutex);
+ pthread_mutex_lock(&data->op_mutex);
data_datum = gdbm_fetch(data->gdbm, key_datum);
- pthread_mutex_unlock(&data->session_mutex);
if (data_datum.dptr != NULL){
/*
* If there is a corresponding entry in the database with active=1 it is stale.
data_datum.dptr = (char *) &entry;
data_datum.dsize = sizeof(ippool_info);
- pthread_mutex_lock(&data->session_mutex);
rcode = gdbm_store(data->gdbm, key_datum, data_datum, GDBM_REPLACE);
- pthread_mutex_unlock(&data->session_mutex);
if (rcode < 0) {
radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",
data->session_db, gdbm_strerror(gdbm_errno));
+ pthread_mutex_unlock(&data->op_mutex);
return RLM_MODULE_FAIL;
}
/* Decrease allocated count from the ip index */
key_datum.dptr = (char *) &entry.ipaddr;
key_datum.dsize = sizeof(uint32_t);
- pthread_mutex_lock(&data->ip_mutex);
data_datum = gdbm_fetch(data->ip, key_datum);
- pthread_mutex_unlock(&data->ip_mutex);
if (data_datum.dptr != NULL){
memcpy(&num, data_datum.dptr, sizeof(int));
free(data_datum.dptr);
DEBUG("rlm_ippool: num: %d",num);
data_datum.dptr = (char *) #
data_datum.dsize = sizeof(int);
- pthread_mutex_lock(&data->ip_mutex);
rcode = gdbm_store(data->ip, key_datum, data_datum, GDBM_REPLACE);
- pthread_mutex_unlock(&data->ip_mutex);
if (rcode < 0) {
radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",
data->ip_index, gdbm_strerror(gdbm_errno));
+ pthread_mutex_unlock(&data->op_mutex);
return RLM_MODULE_FAIL;
}
}
}
}
}
+
+ pthread_mutex_unlock(&data->op_mutex);
+
/*
* If there is a Framed-IP-Address attribute in the reply, check for override
*/
/*
* Walk through the database searching for an active=0 entry.
+ * We search twice. Once to see if we have an active entry with the same callerid
+ * so that MPPP can work ok and then once again to find a free entry.
*/
- pthread_mutex_lock(&data->session_mutex);
- key_datum = gdbm_firstkey(data->gdbm);
- while(key_datum.dptr){
- data_datum = gdbm_fetch(data->gdbm, key_datum);
- if (data_datum.dptr){
- memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
- free(data_datum.dptr);
- /*
- * If we find an entry for the same caller-id and nas with active=1
- * then we use that for multilink (MPPP) to work properly.
- */
- if (cli != NULL && strcmp(entry.cli,cli) == 0 && entry.active){
- memcpy(&key,key_datum.dptr,sizeof(ippool_key));
- if (!strcmp(key.nas,nas))
- break;
+ pthread_mutex_lock(&data->op_mutex);
+
+ key_datum.dptr = NULL;
+ if (cli != NULL){
+ key_datum = gdbm_firstkey(data->gdbm);
+ while(key_datum.dptr){
+ data_datum = gdbm_fetch(data->gdbm, key_datum);
+ if (data_datum.dptr){
+ memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
+ free(data_datum.dptr);
+ /*
+ * If we find an entry for the same caller-id and nas with active=1
+ * then we use that for multilink (MPPP) to work properly.
+ */
+ if (strcmp(entry.cli,cli) == 0 && entry.active){
+ memcpy(&key,key_datum.dptr,sizeof(ippool_key));
+ if (!strcmp(key.nas,nas))
+ break;
+ }
}
- if (entry.active == 0){
- datum tmp;
+ nextkey = gdbm_nextkey(data->gdbm, key_datum);
+ free(key_datum.dptr);
+ key_datum = nextkey;
+ }
+ }
- tmp.dptr = (char *) &entry.ipaddr;
- tmp.dsize = sizeof(uint32_t);
- pthread_mutex_lock(&data->ip_mutex);
- data_datum = gdbm_fetch(data->ip, tmp);
- pthread_mutex_unlock(&data->ip_mutex);
+ if (key_datum.dptr == NULL){
+ key_datum = gdbm_firstkey(data->gdbm);
+ while(key_datum.dptr){
+ data_datum = gdbm_fetch(data->gdbm, key_datum);
+ if (data_datum.dptr){
+ memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
+ free(data_datum.dptr);
/*
- * If we find an entry in the ip index and the number is zero (meaning
- * that we haven't allocated the same ip address to another nas/port pair)
- * or if we don't find an entry then delete the session entry so
- * that we can change the key (nas/port)
- * Else we don't delete the session entry since we haven't yet deallocated the
- * corresponding ip address and we continue our search.
+ * Find an entry with active == 0
*/
+ if (entry.active == 0){
+ datum tmp;
- if (data_datum.dptr){
- memcpy(&num,data_datum.dptr, sizeof(int));
- free(data_datum.dptr);
- if (num == 0){
+ tmp.dptr = (char *) &entry.ipaddr;
+ tmp.dsize = sizeof(uint32_t);
+ data_datum = gdbm_fetch(data->ip, tmp);
+
+ /*
+ * If we find an entry in the ip index and the number is zero (meaning
+ * that we haven't allocated the same ip address to another nas/port pair)
+ * or if we don't find an entry then delete the session entry so
+ * that we can change the key (nas/port)
+ * Else we don't delete the session entry since we haven't yet deallocated the
+ * corresponding ip address and we continue our search.
+ */
+
+ if (data_datum.dptr){
+ memcpy(&num,data_datum.dptr, sizeof(int));
+ free(data_datum.dptr);
+ if (num == 0){
+ delete = 1;
+ break;
+ }
+ }
+ else{
delete = 1;
break;
}
}
- else{
- delete = 1;
- break;
- }
}
+ nextkey = gdbm_nextkey(data->gdbm, key_datum);
+ free(key_datum.dptr);
+ key_datum = nextkey;
}
- nextkey = gdbm_nextkey(data->gdbm, key_datum);
- free(key_datum.dptr);
- key_datum = nextkey;
}
- pthread_mutex_unlock(&data->session_mutex);
+ pthread_mutex_unlock(&data->op_mutex);
/*
* If we have found a free entry set active to 1 then add a Framed-IP-Address attribute to
* the reply
data_datum.dptr = (char *) &entry;
data_datum.dsize = sizeof(ippool_info);
+ pthread_mutex_lock(&data->op_mutex);
if (delete){
/*
* Delete the entry so that we can change the key
*/
- pthread_mutex_lock(&data->session_mutex);
gdbm_delete(data->gdbm, key_datum);
- pthread_mutex_unlock(&data->session_mutex);
}
free(key_datum.dptr);
memset(key.nas,0,MAX_NAS_NAME_SIZE);
key_datum.dsize = sizeof(ippool_key);
DEBUG2("rlm_ippool: Allocating ip to nas/port: %s/%u",key.nas,key.port);
- pthread_mutex_lock(&data->session_mutex);
rcode = gdbm_store(data->gdbm, key_datum, data_datum, GDBM_REPLACE);
- pthread_mutex_unlock(&data->session_mutex);
if (rcode < 0) {
radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",
data->session_db, gdbm_strerror(gdbm_errno));
+ pthread_mutex_unlock(&data->op_mutex);
return RLM_MODULE_FAIL;
}
/* Increase the ip index count */
key_datum.dptr = (char *) &entry.ipaddr;
key_datum.dsize = sizeof(uint32_t);
- pthread_mutex_lock(&data->ip_mutex);
data_datum = gdbm_fetch(data->ip, key_datum);
- pthread_mutex_unlock(&data->ip_mutex);
if (data_datum.dptr){
memcpy(&num,data_datum.dptr,sizeof(int));
free(data_datum.dptr);
DEBUG("rlm_ippool: num: %d",num);
data_datum.dptr = (char *) #
data_datum.dsize = sizeof(int);
- pthread_mutex_lock(&data->ip_mutex);
rcode = gdbm_store(data->ip, key_datum, data_datum, GDBM_REPLACE);
- pthread_mutex_unlock(&data->ip_mutex);
if (rcode < 0) {
radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",
data->ip_index, gdbm_strerror(gdbm_errno));
+ pthread_mutex_unlock(&data->op_mutex);
return RLM_MODULE_FAIL;
}
+ pthread_mutex_unlock(&data->op_mutex);
DEBUG("rlm_ippool: Allocated ip %s to client on nas %s,port %u",ip_ntoa(str,entry.ipaddr),
gdbm_close(data->ip);
free(data->session_db);
free(data->ip_index);
- pthread_mutex_destroy(&data->session_mutex);
- pthread_mutex_destroy(&data->ip_mutex);
+ pthread_mutex_destroy(&data->op_mutex);
free(instance);
return 0;