/*
- * rlm_sqlippool.c
+ * rlm_sqlippool.c rlm_sqlippool - FreeRADIUS SQL IP Pool Module
*
* Version: $Id$
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
* Copyright 2002 Globe.Net Communications Limited
+ * Copyright 2006 The FreeRADIUS server project
+ * Copyright 2006 Suntel Communications
*/
-#include "config.h"
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <netinet/in.h>
+#include <freeradius-devel/radiusd.h>
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
-#include "modpriv.h"
+#include <ctype.h>
-#include "rlm_sql.h"
-#include "ip_set.h"
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/modpriv.h>
-static const char rcsid[] = "$Id$";
+#include <rlm_sql.h>
/*
* Define a structure for our module configuration.
typedef struct rlm_sqlippool_t {
char *sql_instance_name;
- uint32_t range_start;
- uint32_t range_stop;
- uint32_t netmask;
int lease_duration;
SQL_INST *sql_inst;
char *pool_name;
- /* Initialization sequence */
- char *init_begin; /* SQL query to begin */
- char *init_query; /* SQL query to select records */
- char *init_delete; /* SQL query to delete records */
- char *init_insert; /* SQL query to insert records */
- char *init_commit; /* SQL query to commit */
- char *init_rollback; /* SQL query to rollback */
-
+ /* We ended up removing the init
+ queries so that its up to user
+ to create the db structure and put the required
+ information in there
+ */
/* Allocation sequence */
char *allocate_begin; /* SQL query to begin */
char *allocate_clear; /* SQL query to clear an IP */
char *allocate_commit; /* SQL query to commit */
char *allocate_rollback; /* SQL query to rollback */
+ char *pool_check; /* Query to check for the existence of the pool */
+
/* Start sequence */
char *start_begin; /* SQL query to begin */
char *start_update; /* SQL query to update an IP entry */
char *off_clear; /* SQL query to clear an entire NAS */
char *off_commit; /* SQL query to commit */
char *off_rollback; /* SQL query to rollback */
+
+ /* Logging Section */
+ char *log_exists; /* There was an ip address already assigned */
+ char *log_success; /* We successfully allocated ip address from pool */
+ char *log_clear; /* We successfully deallocated ip address from pool */
+ char *log_failed; /* Failed to allocate ip from the pool */
+ char *log_nopool; /* There was no Framed-IP-Address but also no Pool-Name */
+
+ /* Reserved to handle 255.255.255.254 Requests */
+ char *defaultpool; /* Default Pool-Name if there is non in the check items */
+
} rlm_sqlippool_t;
/*
static CONF_PARSER module_config[] = {
{"sql-instance-name",PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,sql_instance_name), NULL, "sql"},
- { "range-start", PW_TYPE_IPADDR, offsetof(rlm_sqlippool_t,range_start), NULL, "0" },
- { "range-stop", PW_TYPE_IPADDR, offsetof(rlm_sqlippool_t,range_stop), NULL, "0" },
- { "netmask", PW_TYPE_IPADDR, offsetof(rlm_sqlippool_t,netmask), NULL, "0" },
{ "lease-duration", PW_TYPE_INTEGER, offsetof(rlm_sqlippool_t,lease_duration), NULL, "86400"},
- { "init-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,init_begin), NULL, "BEGIN" },
- { "init-query", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,init_query), NULL, "" },
- { "init-delete", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,init_delete), NULL, "" },
- { "init-insert", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,init_insert), NULL, "" },
- { "init-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,init_commit), NULL, "COMMIT" },
- { "init-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,init_rollback), NULL, "ROLLBACK" },
+ { "pool-name" , PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, pool_name), NULL, ""},
- { "allocate-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_begin), NULL, "BEGIN" },
+ { "allocate-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_begin), NULL, "START TRANSACTION" },
{ "allocate-clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_clear), NULL, "" },
{ "allocate-find", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_find), NULL, "" },
{ "allocate-update", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_update), NULL, "" },
{ "allocate-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_commit), NULL, "COMMIT" },
{ "allocate-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_rollback), NULL, "ROLLBACK" },
- { "start-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,start_begin), NULL, "BEGIN" },
+ { "pool-check", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,pool_check), NULL, "" },
+
+ { "start-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,start_begin), NULL, "START TRANSACTION" },
{ "start-update", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,start_update), NULL, "" },
{ "start-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,start_commit), NULL, "COMMIT" },
{ "start-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,start_rollback), NULL, "ROLLBACK" },
- { "alive-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,alive_begin), NULL, "BEGIN" },
+ { "alive-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,alive_begin), NULL, "START TRANSACTION" },
{ "alive-update", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,alive_update), NULL, "" },
{ "alive-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,alive_commit), NULL, "COMMIT" },
{ "alive-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,alive_rollback), NULL, "ROLLBACK" },
- { "stop-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,stop_begin), NULL, "BEGIN" },
+ { "stop-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,stop_begin), NULL, "START TRANSACTION" },
{ "stop-clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,stop_clear), NULL, "" },
{ "stop-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,stop_commit), NULL, "COMMIT" },
{ "stop-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,stop_rollback), NULL, "ROLLBACK" },
- { "on-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,on_begin), NULL, "BEGIN" },
+ { "on-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,on_begin), NULL, "START TRANSACTION" },
{ "on-clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,on_clear), NULL, "" },
{ "on-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,on_commit), NULL, "COMMIT" },
{ "on-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,on_rollback), NULL, "ROLLBACK" },
- { "off-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,off_begin), NULL, "BEGIN" },
+ { "off-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,off_begin), NULL, "START TRANSACTION" },
{ "off-clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,off_clear), NULL, "" },
{ "off-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,off_commit), NULL, "COMMIT" },
{ "off-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,off_rollback), NULL, "ROLLBACK" },
+ { "sqlippool_log_exists", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_exists), NULL, "" },
+ { "sqlippool_log_success", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_success), NULL, "" },
+ { "sqlippool_log_clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_clear), NULL, "" },
+ { "sqlippool_log_failed", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_failed), NULL, "" },
+ { "sqlippool_log_nopool", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_nopool), NULL, "" },
+
+ { "defaultpool", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, defaultpool), NULL, "main_pool" },
+
{ NULL, -1, 0, NULL, NULL }
};
/*
* We check if we're inside an open brace. If we are
* then we assume this brace is NOT literal, but is
- * a closing brace and apply it
+ * a closing brace and apply it
*/
if((c == '}') && openbraces) {
openbraces--;
*q++ = *p;
break;
case 'P': /* pool name */
- strNcpy(q, data->pool_name, freespace);
+ strlcpy(q, data->pool_name, freespace);
q += strlen(q);
break;
case 'I': /* IP address */
if (param && param_len > 0) {
if (param_len > freespace) {
- strNcpy(q, param, freespace);
+ strlcpy(q, param, freespace);
q += strlen(q);
}
else {
break;
case 'J': /* lease duration */
sprintf(tmp, "%d", data->lease_duration);
- strNcpy(q, tmp, freespace);
+ strlcpy(q, tmp, freespace);
q += strlen(q);
break;
default:
*/
if (request) {
if (!radius_xlat(query, sizeof(query), expansion, request, NULL)) {
- radlog(L_ERR, "sqlippool_command: xlat failed.");
+ radlog(L_ERR, "sqlippool_command: xlat failed on: '%s'", query);
return 0;
}
}
#if 0
DEBUG2("sqlippool_command: '%s'", query);
#endif
-
if (rlm_sql_query(sqlsocket, data->sql_inst, query)){
- radlog(L_ERR, "sqlippool_command: database query error");
+ radlog(L_ERR, "sqlippool_command: database query error in: '%s'", query);
return 0;
}
(data->sql_inst->module->sql_finish_query)(sqlsocket, data->sql_inst->config);
-
return 0;
}
char expansion[MAX_STRING_LEN * 4];
char query[MAX_STRING_LEN * 4];
SQL_ROW row;
- int r;
+ int rlen, retval = 0;
sqlippool_expand(expansion, sizeof(expansion), fmt, instance, param, param_len);
#if 0
DEBUG2("sqlippool_query1: '%s'", query);
#endif
-
if (rlm_sql_select_query(sqlsocket, data->sql_inst, query)){
radlog(L_ERR, "sqlippool_query1: database query error");
out[0] = '\0';
return 0;
}
- r = rlm_sql_fetch_row(sqlsocket, data->sql_inst);
- (data->sql_inst->module->sql_finish_select_query)(sqlsocket, data->sql_inst->config);
-
- if (r) {
- DEBUG("sqlippool_query1: SQL query did not succeed");
- out[0] = '\0';
- return 0;
- }
+ out[0] = '\0';
- row = sqlsocket->row;
- if (row == NULL) {
- DEBUG("sqlippool_query1: SQL query did not return any results");
- out[0] = '\0';
- return 0;
- }
-
- if (row[0] == NULL){
- DEBUG("sqlippool_query1: row[0] returned NULL");
- out[0] = '\0';
- return 0;
- }
-
- r = strlen(row[0]);
- if (r >= outlen){
- DEBUG("sqlippool_query1: insufficient string space");
- out[0] = '\0';
- return 0;
- }
-
- strncpy(out, row[0], r);
- out[r] = '\0';
-
- return r;
-}
-
-/*
- * Start the database query expecting multiple result rows
- */
-static int sqlippool_queryn(const char * fmt, SQLSOCK * sqlsocket, void * instance, REQUEST * request, char * param, int param_len)
-{
- rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
- char expansion[MAX_STRING_LEN * 4];
- char query[MAX_STRING_LEN * 4];
-
- sqlippool_expand(expansion, sizeof(expansion), fmt, instance, param, param_len);
-
- /*
- * Do an xlat on the provided string
- */
- if (request) {
- if (!radius_xlat(query, sizeof(query), expansion, request, NULL)) {
- radlog(L_ERR, "sqlippool_command: xlat failed.");
- return 0;
- }
- }
- else {
- strcpy(query, expansion);
- }
-
-#if 1
- DEBUG2("sqlippool_queryn: '%s'", query);
-#endif
+ if (!rlm_sql_fetch_row(sqlsocket, data->sql_inst)) {
+ if (sqlsocket->row) {
+ if (sqlsocket->row[0]) {
+ if ((rlen = strlen(sqlsocket->row[0])) < outlen) {
+ strcpy(out, sqlsocket->row[0]);
+ retval = rlen;
+ } else DEBUG("sqlippool_query1: insufficient string space");
+ } else DEBUG("sqlippool_query1: row[0] returned NULL");
+ } else DEBUG("sqlippool_query1: SQL query did not return any results");
+ } else DEBUG("sqlippool_query1: SQL query did not succeed");
- if (rlm_sql_select_query(sqlsocket, data->sql_inst, query)){
- radlog(L_ERR, "sqlippool_query1: database query error");
- return 0;
- }
-
- return 1;
+ (data->sql_inst->module->sql_finish_select_query)(sqlsocket, data->sql_inst->config);
+ return retval;
}
-/*
- * Fetch the next record from the multiple result set
- */
-static int sqlippool_queryn_fetch(char * out, int outlen, SQLSOCK * sqlsocket, void * instance)
+static int sqlippool_initialize_sql(void * instance)
{
- rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
- SQL_ROW row;
- int r;
-
- r = rlm_sql_fetch_row(sqlsocket, data->sql_inst);
-
- if (r) {
- DEBUG("sqlippool_queryn: SQL query did not succeed");
- out[0] = '\0';
- return 0;
- }
-
- row = sqlsocket->row;
- if (row == NULL) {
- out[0] = '\0';
- return 0;
- }
-
- if (row[0] == NULL){
- DEBUG("sqlippool_queryn: row[0] returned NULL");
- out[0] = '\0';
- return 0;
- }
-
- r = strlen(row[0]);
- if (r >= outlen){
- DEBUG("sqlippool_queryn: insufficient string space");
- out[0] = '\0';
- return 0;
- }
-
- strncpy(out, row[0], r);
- out[r] = '\0';
- return r;
-}
-
-/*
- * Query the database expecting a multiple result rows
- */
-static int sqlippool_queryn_end(SQLSOCK * sqlsocket, void * instance)
-{
rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
- (data->sql_inst->module->sql_finish_select_query)(sqlsocket, data->sql_inst->config);
-
- return 1;
-}
-
-static int sqlippool_initialize_range(void * instance)
-{
- rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
SQLSOCK * sqlsocket;
- ip_set ips;
- char ip_buffer[MAX_STRING_LEN];
- int ip_buffer_len;
-
- uint32_t h_start; /* start in host order */
- uint32_t h_stop; /* stop in host order */
- uint32_t h_netmask; /* netmask in host order */
-
- h_start = ntohl(data->range_start);
- h_stop = ntohl(data->range_stop);
- h_netmask = ntohl(data->netmask);
-
- ip_set_initialize(&ips);
- /*
- * Now run the initialization sequence
- */
sqlsocket = sql_get_socket(data->sql_inst);
if (sqlsocket == NULL) {
DEBUG("rlm_sqlippool: cannot allocate sql connection for initialization sequence");
return 0;
}
- /*
- * BEGIN
- */
- sqlippool_command(data->init_begin, sqlsocket, instance, NULL,
- (char *) NULL, 0);
-
- /*
- * QUERY
- */
- sqlippool_queryn(data->init_query, sqlsocket, instance, NULL,
- (char *) NULL, 0);
-
- while (1)
- {
- uint32_t ip;
- uint32_t h_ip; /* ip in host order */
-
- ip_buffer_len = sqlippool_queryn_fetch(ip_buffer, sizeof(ip_buffer),
- sqlsocket, instance);
- if (ip_buffer_len == 0)
- break;
-
- ip = ip_addr(ip_buffer);
- if (ip == INADDR_NONE) {
- radlog(L_ERR, "sqlippool_initialize_range: invalid IP number in pool");
- /* XXX store and delete */
- continue;
- }
-
- h_ip = ntohl(ip);
- ip_set_add(&ips, h_ip);
- }
-
- sqlippool_queryn_end(sqlsocket, data);
-
- {
- int i;
-
- DEBUG(" len = %d, allocated = %d", ips.length, ips.allocated);
- for (i = 0; i < ips.length; i++) {
- DEBUG(" %d: %08x-%08x",
- i,
- ips.ranges[i].h_start,
- ips.ranges[i].h_finish);
- }
- }
-
- /*
- * Loop over the rows and delete any entries are not in the pool
- */
- {
- int i;
- int h_ip;
- uint32_t or_result;
-
- for (i = 0; i < ips.length; i++) {
- for (h_ip = ips.ranges[i].h_start; h_ip <= ips.ranges[i].h_finish; h_ip++) {
- if (h_ip < h_start)
- ;
- else if (h_ip > h_stop)
- ;
- else {
- or_result = h_ip | h_netmask;
- if (or_result == h_netmask || or_result == 0xffffffff)
- ;
- else
- continue;
- }
-
- ip_ntoa(ip_buffer, htonl(h_ip));
-
- /*
- * DELETE
- */
- sqlippool_command(data->init_delete, sqlsocket, instance, NULL,
- ip_buffer, strlen(ip_buffer));
- }
- }
- }
-
- /*
- * Loop over the range and insert any entries are not in the database
- */
- {
- uint32_t h_ip; /* ip in host order */
- uint32_t or_result;
-
- h_start = ntohl(data->range_start);
- h_stop = ntohl(data->range_stop);
- h_netmask = ntohl(data->netmask);
-
- for (h_ip = h_start; h_ip <= h_stop; h_ip++) {
- /*
- * Network and broadcast addresses are excluded
- */
- or_result = h_ip | h_netmask;
- if (or_result == h_netmask || or_result == 0xffffffff) {
- continue;
- }
-
- if (ip_set_test(&ips, h_ip))
- continue;
-
- ip_ntoa(ip_buffer, htonl(h_ip));
-
- /*
- * INSERT
- */
- sqlippool_command(data->init_insert, sqlsocket, instance, NULL,
- ip_buffer, strlen(ip_buffer));
- }
- }
-
- /*
- * COMMIT
- */
- sqlippool_command(data->init_commit, sqlsocket, instance, NULL,
- (char *) NULL, 0);
-
- sql_release_socket(data->sql_inst, sqlsocket);
-
- ip_set_free(&ips);
-
return 1;
}
/*
* Check that all the queries are in place
*/
- if (data->init_query == NULL || strlen(data->init_query) == 0) {
- radlog(L_ERR, "rlm_sqlippool: the 'init-query' statement must be set.");
- free(data);
- exit(0);
- }
-
- if (data->init_delete == NULL || strlen(data->init_delete) == 0) {
- radlog(L_ERR, "rlm_sqlippool: the 'init-delete' statement must be set.");
- free(data);
- exit(0);
- }
-
- if (data->init_insert == NULL || strlen(data->init_insert) == 0) {
- radlog(L_ERR, "rlm_sqlippool: the 'init-insert' statement must be set.");
- free(data);
- exit(0);
- }
if (data->allocate_clear == NULL || strlen(data->allocate_clear) == 0) {
radlog(L_ERR, "rlm_sqlippool: the 'allocate-clear' statement must be set.");
else
data->pool_name = strdup("ippool");
- data->sql_inst = (SQL_INST *)(find_module_instance(cf_section_find("modules"), data->sql_instance_name))->insthandle;
- if (data->sql_inst == NULL) {
+ if ( !(data->sql_inst = (SQL_INST *) (find_module_instance(cf_section_find("modules"), data->sql_instance_name))->insthandle) )
+ {
radlog(L_ERR, "sqlippool_instantiate: failed to find sql instance named %s", data->sql_instance_name);
free(data);
exit(0);
}
- sqlippool_initialize_range(data);
-
+ sqlippool_initialize_sql(data);
*instance = data;
return 0;
}
+
+/*
+ * if we have something to log, then we log it
+ * otherwise we return the retcode as soon as possible
+ */
+static int do_logging(char *str, int retcode)
+{
+ if (strlen(str))
+ radlog(L_INFO,"%s", str);
+ return retcode;
+}
+
+
/*
* Allocate an IP number from the pool.
*/
uint32_t ip_allocation;
VALUE_PAIR * vp;
SQLSOCK * sqlsocket;
+ lrad_ipaddr_t ipaddr;
+
+ VALUE_PAIR *callingsid;
+ VALUE_PAIR *pair;
+
+ int do_callingsid = 0;
+ int do_calledsid = 0;
+
+ char logstr[MAX_STRING_LEN];
/*
* If there is a Framed-IP-Address attribute in the reply do nothing
*/
if (pairfind(request->reply->vps, PW_FRAMED_IP_ADDRESS) != NULL) {
+ /* We already have a Framed-IP-Address */
+ radius_xlat(logstr, sizeof(logstr), data->log_exists, request, NULL);
DEBUG("rlm_sqlippool: Framed-IP-Address already exists");
- return RLM_MODULE_NOOP;
- }
- /*
- * Check if Pool-Name attribute exists. If it exists check our name and
- * run only if they match
- */
- if ((vp = pairfind(request->config_items, PW_POOL_NAME)) != NULL) {
- if (data->pool_name == NULL || strcmp(data->pool_name, vp->vp_strvalue) != 0) {
- DEBUG("rlm_sqlippool: pool_name does not match");
- return RLM_MODULE_NOOP;
- }
- }
- else {
- DEBUG("rlm_sqlippool: missing pool_name");
- return RLM_MODULE_NOOP;
+ return do_logging(logstr, RLM_MODULE_NOOP);
}
+ if (pairfind(request->config_items, PW_POOL_NAME) == NULL) {
+ DEBUG("rlm_sqlippool: We Dont have Pool-Name in check items.. Lets do nothing..");
+ radius_xlat(logstr, sizeof(logstr), data->log_nopool, request, NULL);
+
+ return do_logging(logstr, RLM_MODULE_NOOP);
+ }
+
if (pairfind(request->packet->vps, PW_NAS_IP_ADDRESS) == NULL) {
DEBUG("rlm_sqlippool: unknown NAS-IP-Address");
return RLM_MODULE_NOOP;
sqlsocket = sql_get_socket(data->sql_inst);
if (sqlsocket == NULL) {
DEBUG("rlm_sqlippool: cannot allocate sql connection");
- return RLM_MODULE_NOOP;
+ return RLM_MODULE_FAIL;
}
/*
allocation_len = sqlippool_query1(allocation, sizeof(allocation),
data->allocate_find, sqlsocket, instance, request,
(char *) NULL, 0);
- DEBUG("rlm_sqlippool: ip=[%s] len=%d", allocation, allocation_len);
if (allocation_len == 0)
- {
+ {
/*
* COMMIT
*/
sqlippool_command(data->allocate_commit, sqlsocket, instance, request,
(char *) NULL, 0);
- DEBUG("rlm_sqlippool: IP number could not be allocated.");
+ /*
+ * Should we perform pool-check ?
+ */
+ if (data->pool_check && *data->pool_check) {
+
+ /*
+ * Ok, so the allocate-find query found nothing ...
+ * Let's check if the pool exists at all
+ */
+ allocation_len = sqlippool_query1(allocation, sizeof(allocation),
+ data->pool_check, sqlsocket, instance, request,
+ (char *) NULL, 0);
+
+ sql_release_socket(data->sql_inst, sqlsocket);
+
+ if (allocation_len) {
+
+ /*
+ * Pool exists after all... So, the failure to allocate
+ * the IP address was most likely due to the depletion
+ * of the pool. In that case, we should return NOTFOUND
+ */
+ DEBUG("rlm_sqlippool: IP address could not be allocated.");
+ radius_xlat(logstr, sizeof(logstr), data->log_failed, request, NULL);
+ return do_logging(logstr, RLM_MODULE_NOTFOUND);
+
+ }
+ /*
+ * Pool doesn't exist in the table. It may be handled by some
+ * other instance of sqlippool, so we should just ignore
+ * this allocation failure and return NOOP
+ */
+ DEBUG("rlm_sqlippool: IP address could not be allocated as not pool exists with that name.");
+ return RLM_MODULE_NOOP;
+
+ }
+
sql_release_socket(data->sql_inst, sqlsocket);
- return RLM_MODULE_NOOP;
- }
- ip_allocation = ip_addr(allocation);
- if (ip_allocation == INADDR_NONE)
- {
- /*
- * Invalid IP number - run INIT-DELETE and complain
- */
+ DEBUG("rlm_sqlippool: IP address could not be allocated.");
+ radius_xlat(logstr, sizeof(logstr), data->log_failed, request, NULL);
- /*
- * INIT_DELETE
- */
- sqlippool_command(data->init_delete, sqlsocket, instance, NULL,
- allocation, allocation_len);
+ return do_logging(logstr, RLM_MODULE_NOOP);
+ }
+
+ /*
+ * FIXME: Make it work with the ipv6 addresses
+ */
+ if ((ip_hton(allocation, AF_INET, &ipaddr) < 0) ||
+ ((ip_allocation = ipaddr.ipaddr.ip4addr.s_addr) == INADDR_NONE))
+ {
/*
* COMMIT
*/
DEBUG("rlm_sqlippool: Invalid IP number [%s] returned from database query.", allocation);
sql_release_socket(data->sql_inst, sqlsocket);
- return RLM_MODULE_NOOP;
+ radius_xlat(logstr, sizeof(logstr), data->log_failed, request, NULL);
+
+ return do_logging(logstr, RLM_MODULE_NOOP);
}
/*
(char *) NULL, 0);
sql_release_socket(data->sql_inst, sqlsocket);
- return RLM_MODULE_OK;
+ radius_xlat(logstr, sizeof(logstr), data->log_success, request, NULL);
+
+ return do_logging(logstr, RLM_MODULE_OK);
}
static int sqlippool_accounting_start(void * instance, REQUEST * request)
static int sqlippool_accounting_stop(void * instance, REQUEST * request)
{
+ char logstr[MAX_STRING_LEN];
+
rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
SQLSOCK * sqlsocket;
(char *) NULL, 0);
sql_release_socket(data->sql_inst, sqlsocket);
+ radius_xlat(logstr, sizeof(logstr), data->log_clear, request, NULL);
- return RLM_MODULE_OK;
+ return do_logging(logstr, RLM_MODULE_OK);
}
static int sqlippool_accounting_on(void * instance, REQUEST * request)
/*
* Check for an Accounting-Stop
- * If we find one and we have allocated an IP to this nas/port combination, deallocate it.
+ * If we find one and we have allocated an IP to this nas/port combination, deallocate it.
*/
static int sqlippool_accounting(void * instance, REQUEST * request)
{
{
rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
- free(data->sql_instance_name);
- free(data->pool_name);
-
- free(data->init_begin);
- free(data->init_query);
- free(data->init_delete);
- free(data->init_insert);
- free(data->init_commit);
- free(data->init_rollback);
-
- free(data->allocate_begin);
- free(data->allocate_clear);
- free(data->allocate_find);
- free(data->allocate_update);
- free(data->allocate_commit);
- free(data->allocate_rollback);
-
- free(data->start_begin);
- free(data->start_update);
- free(data->start_commit);
- free(data->start_rollback);
-
- free(data->alive_begin);
- free(data->alive_update);
- free(data->alive_commit);
- free(data->alive_rollback);
-
- free(data->stop_begin);
- free(data->stop_clear);
- free(data->stop_commit);
- free(data->stop_rollback);
-
- free(data->on_begin);
- free(data->on_clear);
- free(data->on_commit);
- free(data->on_rollback);
-
- free(data->off_begin);
- free(data->off_clear);
- free(data->off_commit);
- free(data->off_rollback);
-
return 0;
}
*/
module_t rlm_sqlippool = {
RLM_MODULE_INIT,
- "sqlippool",
+ "SQL IP Pool",
RLM_TYPE_THREAD_SAFE, /* type */
sqlippool_instantiate, /* instantiation */
sqlippool_detach, /* detach */
NULL, /* pre-proxy */
NULL, /* post-proxy */
sqlippool_postauth /* post-auth */
- }
+ },
};