2 * rlm_sqlippool.c rlm_sqlippool - FreeRADIUS SQL IP Pool Module
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Copyright 2002 Globe.Net Communications Limited
21 * Copyright 2006 The FreeRADIUS server project
22 * Copyright 2006 Suntel Communications
25 #include <freeradius-devel/ident.h>
28 #include <freeradius-devel/autoconf.h>
29 #include <freeradius-devel/libradius.h>
34 #include <freeradius-devel/radiusd.h>
35 #include <freeradius-devel/modules.h>
36 #include <freeradius-devel/modpriv.h>
41 * Define a structure for our module configuration.
43 typedef struct rlm_sqlippool_t {
44 char *sql_instance_name;
52 /* We ended up removing the init
53 queries so that its up to user
54 to create the db structure and put the required
57 /* Allocation sequence */
58 char *allocate_begin; /* SQL query to begin */
59 char *allocate_clear; /* SQL query to clear an IP */
60 char *allocate_find; /* SQL query to find an unused IP */
61 char *allocate_update; /* SQL query to mark an IP as used */
62 char *allocate_commit; /* SQL query to commit */
63 char *allocate_rollback; /* SQL query to rollback */
65 char *pool_check; /* Query to check for the existence of the pool */
68 char *start_begin; /* SQL query to begin */
69 char *start_update; /* SQL query to update an IP entry */
70 char *start_commit; /* SQL query to commit */
71 char *start_rollback; /* SQL query to rollback */
74 char *alive_begin; /* SQL query to begin */
75 char *alive_update; /* SQL query to update an IP entry */
76 char *alive_commit; /* SQL query to commit */
77 char *alive_rollback; /* SQL query to rollback */
80 char *stop_begin; /* SQL query to begin */
81 char *stop_clear; /* SQL query to clear an IP */
82 char *stop_commit; /* SQL query to commit */
83 char *stop_rollback; /* SQL query to rollback */
86 char *on_begin; /* SQL query to begin */
87 char *on_clear; /* SQL query to clear an entire NAS */
88 char *on_commit; /* SQL query to commit */
89 char *on_rollback; /* SQL query to rollback */
92 char *off_begin; /* SQL query to begin */
93 char *off_clear; /* SQL query to clear an entire NAS */
94 char *off_commit; /* SQL query to commit */
95 char *off_rollback; /* SQL query to rollback */
98 char *log_exists; /* There was an ip address already assigned */
99 char *log_success; /* We successfully allocated ip address from pool */
100 char *log_clear; /* We successfully deallocated ip address from pool */
101 char *log_failed; /* Failed to allocate ip from the pool */
102 char *log_nopool; /* There was no Framed-IP-Address but also no Pool-Name */
104 /* Reserved to handle 255.255.255.254 Requests */
105 char *defaultpool; /* Default Pool-Name if there is non in the check items */
110 * A mapping of configuration file names to internal variables.
112 * Note that the string is dynamically allocated, so it MUST
113 * be freed. When the configuration file parse re-reads the string,
114 * it free's the old one, and strdup's the new one, placing the pointer
115 * to the strdup'd string into 'config.string'. This gets around
118 static CONF_PARSER module_config[] = {
119 {"sql-instance-name",PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,sql_instance_name), NULL, "sql"},
121 { "lease-duration", PW_TYPE_INTEGER, offsetof(rlm_sqlippool_t,lease_duration), NULL, "86400"},
123 { "pool-name" , PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, pool_name), NULL, ""},
125 { "allocate-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_begin), NULL, "START TRANSACTION" },
126 { "allocate-clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_clear), NULL, "" },
127 { "allocate-find", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_find), NULL, "" },
128 { "allocate-update", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_update), NULL, "" },
129 { "allocate-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_commit), NULL, "COMMIT" },
130 { "allocate-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_rollback), NULL, "ROLLBACK" },
132 { "pool-check", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,pool_check), NULL, "" },
134 { "start-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,start_begin), NULL, "START TRANSACTION" },
135 { "start-update", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,start_update), NULL, "" },
136 { "start-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,start_commit), NULL, "COMMIT" },
137 { "start-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,start_rollback), NULL, "ROLLBACK" },
139 { "alive-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,alive_begin), NULL, "START TRANSACTION" },
140 { "alive-update", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,alive_update), NULL, "" },
141 { "alive-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,alive_commit), NULL, "COMMIT" },
142 { "alive-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,alive_rollback), NULL, "ROLLBACK" },
144 { "stop-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,stop_begin), NULL, "START TRANSACTION" },
145 { "stop-clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,stop_clear), NULL, "" },
146 { "stop-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,stop_commit), NULL, "COMMIT" },
147 { "stop-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,stop_rollback), NULL, "ROLLBACK" },
149 { "on-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,on_begin), NULL, "START TRANSACTION" },
150 { "on-clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,on_clear), NULL, "" },
151 { "on-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,on_commit), NULL, "COMMIT" },
152 { "on-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,on_rollback), NULL, "ROLLBACK" },
154 { "off-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,off_begin), NULL, "START TRANSACTION" },
155 { "off-clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,off_clear), NULL, "" },
156 { "off-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,off_commit), NULL, "COMMIT" },
157 { "off-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,off_rollback), NULL, "ROLLBACK" },
159 { "sqlippool_log_exists", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_exists), NULL, "" },
160 { "sqlippool_log_success", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_success), NULL, "" },
161 { "sqlippool_log_clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_clear), NULL, "" },
162 { "sqlippool_log_failed", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_failed), NULL, "" },
163 { "sqlippool_log_nopool", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_nopool), NULL, "" },
165 { "defaultpool", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, defaultpool), NULL, "main_pool" },
167 { NULL, -1, 0, NULL, NULL }
171 * Replace %<whatever> in a string.
178 static int sqlippool_expand(char * out, int outlen, const char * fmt, void * instance, char * param, int param_len)
180 rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
183 char tmp[40]; /* For temporary storing of integers */
188 for (p = fmt; *p ; p++) {
192 /* Calculate freespace in output */
193 freespace = outlen - (q - out);
198 if (c != '%' && c != '$' && c != '\\') {
200 * We check if we're inside an open brace. If we are
201 * then we assume this brace is NOT literal, but is
202 * a closing brace and apply it
204 if((c == '}') && openbraces) {
237 case 'P': /* pool name */
238 strlcpy(q, data->pool_name, freespace);
241 case 'I': /* IP address */
242 if (param && param_len > 0) {
243 if (param_len > freespace) {
244 strlcpy(q, param, freespace);
248 memcpy(q, param, param_len);
253 case 'J': /* lease duration */
254 sprintf(tmp, "%d", data->lease_duration);
255 strlcpy(q, tmp, freespace);
268 DEBUG2("sqlippool_expand: '%s'", out);
275 * Query the database executing a command with no result rows
277 static int sqlippool_command(const char * fmt, SQLSOCK * sqlsocket, void * instance, REQUEST * request, char * param, int param_len)
279 rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
280 char expansion[MAX_STRING_LEN * 4];
281 char query[MAX_STRING_LEN * 4];
283 sqlippool_expand(expansion, sizeof(expansion), fmt, instance, param, param_len);
286 * Do an xlat on the provided string
289 if (!radius_xlat(query, sizeof(query), expansion, request, NULL)) {
290 radlog(L_ERR, "sqlippool_command: xlat failed on: '%s'", query);
295 strcpy(query, expansion);
299 DEBUG2("sqlippool_command: '%s'", query);
301 if (rlm_sql_query(sqlsocket, data->sql_inst, query)){
302 radlog(L_ERR, "sqlippool_command: database query error in: '%s'", query);
306 (data->sql_inst->module->sql_finish_query)(sqlsocket, data->sql_inst->config);
311 * Query the database expecting a single result row
313 static int sqlippool_query1(char * out, int outlen, const char * fmt, SQLSOCK * sqlsocket, void * instance, REQUEST * request, char * param, int param_len)
315 rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
316 char expansion[MAX_STRING_LEN * 4];
317 char query[MAX_STRING_LEN * 4];
319 int rlen, retval = 0;
321 sqlippool_expand(expansion, sizeof(expansion), fmt, instance, param, param_len);
324 * Do an xlat on the provided string
327 if (!radius_xlat(query, sizeof(query), expansion, request, NULL)) {
328 radlog(L_ERR, "sqlippool_command: xlat failed.");
334 strcpy(query, expansion);
338 DEBUG2("sqlippool_query1: '%s'", query);
340 if (rlm_sql_select_query(sqlsocket, data->sql_inst, query)){
341 radlog(L_ERR, "sqlippool_query1: database query error");
348 if (!rlm_sql_fetch_row(sqlsocket, data->sql_inst)) {
349 if (sqlsocket->row) {
350 if (sqlsocket->row[0]) {
351 if ((rlen = strlen(sqlsocket->row[0])) < outlen) {
352 strcpy(out, sqlsocket->row[0]);
354 } else DEBUG("sqlippool_query1: insufficient string space");
355 } else DEBUG("sqlippool_query1: row[0] returned NULL");
356 } else DEBUG("sqlippool_query1: SQL query did not return any results");
357 } else DEBUG("sqlippool_query1: SQL query did not succeed");
359 (data->sql_inst->module->sql_finish_select_query)(sqlsocket, data->sql_inst->config);
363 static int sqlippool_initialize_sql(void * instance)
366 rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
370 sqlsocket = sql_get_socket(data->sql_inst);
371 if (sqlsocket == NULL) {
372 DEBUG("rlm_sqlippool: cannot allocate sql connection for initialization sequence");
380 * Do any per-module initialization that is separate to each
381 * configured instance of the module. e.g. set up connections
382 * to external databases, read configuration files, set up
383 * dictionary entries, etc.
385 * If configuration information is given in the config section
386 * that must be referenced in later calls, store a handle to it
387 * in *instance otherwise put a null pointer there.
389 static int sqlippool_instantiate(CONF_SECTION * conf, void ** instance)
391 rlm_sqlippool_t * data;
392 char * pool_name = NULL;
395 * Set up a storage area for instance data
397 data = rad_malloc(sizeof(*data));
398 memset(data, 0, sizeof(*data));
401 * If the configuration parameters can't be parsed, then
404 if (cf_section_parse(conf, data, module_config) < 0) {
409 if (data->sql_instance_name == NULL || strlen(data->sql_instance_name) == 0) {
410 radlog(L_ERR, "rlm_sqlippool: the 'sql-instance-name' variable must be set.");
416 * Check that all the queries are in place
419 if (data->allocate_clear == NULL || strlen(data->allocate_clear) == 0) {
420 radlog(L_ERR, "rlm_sqlippool: the 'allocate-clear' statement must be set.");
425 if (data->allocate_find == NULL || strlen(data->allocate_find) == 0) {
426 radlog(L_ERR, "rlm_sqlippool: the 'allocate_find' statement must be set.");
431 if (data->allocate_update == NULL || strlen(data->allocate_update) == 0) {
432 radlog(L_ERR, "rlm_sqlippool: the 'allocate_update' statement must be set.");
437 if (data->start_update == NULL || strlen(data->start_update) == 0) {
438 radlog(L_ERR, "rlm_sqlippool: the 'start-update' statement must be set.");
443 if (data->alive_update == NULL || strlen(data->alive_update) == 0) {
444 radlog(L_ERR, "rlm_sqlippool: the 'alive-update' statement must be set.");
449 if (data->stop_clear == NULL || strlen(data->stop_clear) == 0) {
450 radlog(L_ERR, "rlm_sqlippool: the 'stop-clear' statement must be set.");
455 if (data->on_clear == NULL || strlen(data->on_clear) == 0) {
456 radlog(L_ERR, "rlm_sqlippool: the 'on-clear' statement must be set.");
461 if (data->off_clear == NULL || strlen(data->off_clear) == 0) {
462 radlog(L_ERR, "rlm_sqlippool: the 'off-clear' statement must be set.");
467 pool_name = cf_section_name2(conf);
468 if (pool_name != NULL)
469 data->pool_name = strdup(pool_name);
471 data->pool_name = strdup("ippool");
473 if ( !(data->sql_inst = (SQL_INST *) (find_module_instance(cf_section_find("modules"), data->sql_instance_name))->insthandle) )
475 radlog(L_ERR, "sqlippool_instantiate: failed to find sql instance named %s", data->sql_instance_name);
480 sqlippool_initialize_sql(data);
487 * if we have something to log, then we log it
488 * otherwise we return the retcode as soon as possible
490 static int do_logging(char *str, int retcode)
493 radlog(L_INFO,"%s", str);
499 * Allocate an IP number from the pool.
501 static int sqlippool_postauth(void *instance, REQUEST * request)
503 rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
504 char allocation[MAX_STRING_LEN];
506 uint32_t ip_allocation;
509 lrad_ipaddr_t ipaddr;
511 VALUE_PAIR *callingsid;
514 int do_callingsid = 0;
515 int do_calledsid = 0;
517 char logstr[MAX_STRING_LEN];
520 * If there is a Framed-IP-Address attribute in the reply do nothing
522 if (pairfind(request->reply->vps, PW_FRAMED_IP_ADDRESS) != NULL) {
523 /* We already have a Framed-IP-Address */
524 radius_xlat(logstr, sizeof(logstr), data->log_exists, request, NULL);
525 DEBUG("rlm_sqlippool: Framed-IP-Address already exists");
527 return do_logging(logstr, RLM_MODULE_NOOP);
530 if (pairfind(request->config_items, PW_POOL_NAME) == NULL) {
531 DEBUG("rlm_sqlippool: We Dont have Pool-Name in check items.. Lets do nothing..");
532 radius_xlat(logstr, sizeof(logstr), data->log_nopool, request, NULL);
534 return do_logging(logstr, RLM_MODULE_NOOP);
537 if (pairfind(request->packet->vps, PW_NAS_IP_ADDRESS) == NULL) {
538 DEBUG("rlm_sqlippool: unknown NAS-IP-Address");
539 return RLM_MODULE_NOOP;
542 if (pairfind(request->packet->vps, PW_NAS_PORT) == NULL) {
543 DEBUG("rlm_sqlippool: unknown NAS-Port");
544 return RLM_MODULE_NOOP;
547 sqlsocket = sql_get_socket(data->sql_inst);
548 if (sqlsocket == NULL) {
549 DEBUG("rlm_sqlippool: cannot allocate sql connection");
550 return RLM_MODULE_FAIL;
556 sqlippool_command(data->allocate_begin, sqlsocket, instance, request,
562 sqlippool_command(data->allocate_clear, sqlsocket, instance, request,
568 allocation_len = sqlippool_query1(allocation, sizeof(allocation),
569 data->allocate_find, sqlsocket, instance, request,
572 if (allocation_len == 0)
577 sqlippool_command(data->allocate_commit, sqlsocket, instance, request,
581 * Should we perform pool-check ?
583 if (data->pool_check && *data->pool_check) {
586 * Ok, so the allocate-find query found nothing ...
587 * Let's check if the pool exists at all
589 allocation_len = sqlippool_query1(allocation, sizeof(allocation),
590 data->pool_check, sqlsocket, instance, request,
593 sql_release_socket(data->sql_inst, sqlsocket);
595 if (allocation_len) {
598 * Pool exists after all... So, the failure to allocate
599 * the IP address was most likely due to the depletion
600 * of the pool. In that case, we should return NOTFOUND
602 DEBUG("rlm_sqlippool: IP address could not be allocated.");
603 radius_xlat(logstr, sizeof(logstr), data->log_failed, request, NULL);
604 return do_logging(logstr, RLM_MODULE_NOTFOUND);
608 * Pool doesn't exist in the table. It may be handled by some
609 * other instance of sqlippool, so we should just ignore
610 * this allocation failure and return NOOP
612 DEBUG("rlm_sqlippool: IP address could not be allocated as not pool exists with that name.");
613 return RLM_MODULE_NOOP;
617 sql_release_socket(data->sql_inst, sqlsocket);
619 DEBUG("rlm_sqlippool: IP address could not be allocated.");
620 radius_xlat(logstr, sizeof(logstr), data->log_failed, request, NULL);
622 return do_logging(logstr, RLM_MODULE_NOOP);
627 * FIXME: Make it work with the ipv6 addresses
629 if ((ip_hton(allocation, AF_INET, &ipaddr) < 0) ||
630 ((ip_allocation = ipaddr.ipaddr.ip4addr.s_addr) == INADDR_NONE))
635 sqlippool_command(data->allocate_commit, sqlsocket, instance, request,
638 DEBUG("rlm_sqlippool: Invalid IP number [%s] returned from database query.", allocation);
639 sql_release_socket(data->sql_inst, sqlsocket);
640 radius_xlat(logstr, sizeof(logstr), data->log_failed, request, NULL);
642 return do_logging(logstr, RLM_MODULE_NOOP);
648 sqlippool_command(data->allocate_update, sqlsocket, instance, request,
649 allocation, allocation_len);
651 DEBUG("rlm_sqlippool: Allocated IP %s [%08x]", allocation, ip_allocation);
653 if ((vp = paircreate(PW_FRAMED_IP_ADDRESS, PW_TYPE_IPADDR)) == NULL) {
654 radlog(L_ERR|L_CONS, "no memory");
655 sql_release_socket(data->sql_inst, sqlsocket);
656 return RLM_MODULE_NOOP;
658 vp->lvalue = ip_allocation;
659 pairadd(&request->reply->vps, vp);
664 sqlippool_command(data->allocate_commit, sqlsocket, instance, request,
667 sql_release_socket(data->sql_inst, sqlsocket);
668 radius_xlat(logstr, sizeof(logstr), data->log_success, request, NULL);
670 return do_logging(logstr, RLM_MODULE_OK);
673 static int sqlippool_accounting_start(void * instance, REQUEST * request)
675 rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
678 if (pairfind(request->packet->vps, PW_NAS_PORT) == NULL) {
679 DEBUG("rlm_ippool: Could not find port number in packet.");
680 return RLM_MODULE_NOOP;
683 if (pairfind(request->packet->vps, PW_NAS_IP_ADDRESS) == NULL) {
684 DEBUG("rlm_ippool: Could not find nas information in packet.");
685 return RLM_MODULE_NOOP;
688 sqlsocket = sql_get_socket(data->sql_inst);
689 if (sqlsocket == NULL) {
690 DEBUG("rlm_sqlippool: cannot allocate sql connection");
691 return RLM_MODULE_NOOP;
697 sqlippool_command(data->start_begin, sqlsocket, instance, request,
703 sqlippool_command(data->start_update, sqlsocket, instance, request,
709 sqlippool_command(data->start_commit, sqlsocket, instance, request,
712 sql_release_socket(data->sql_inst, sqlsocket);
714 return RLM_MODULE_OK;
717 static int sqlippool_accounting_alive(void * instance, REQUEST * request)
719 rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
722 if (pairfind(request->packet->vps, PW_NAS_PORT) == NULL) {
723 DEBUG("rlm_ippool: Could not find port number in packet.");
724 return RLM_MODULE_NOOP;
727 if (pairfind(request->packet->vps, PW_NAS_IP_ADDRESS) == NULL) {
728 DEBUG("rlm_ippool: Could not find nas information in packet.");
729 return RLM_MODULE_NOOP;
732 sqlsocket = sql_get_socket(data->sql_inst);
733 if (sqlsocket == NULL) {
734 DEBUG("rlm_sqlippool: cannot allocate sql connection");
735 return RLM_MODULE_NOOP;
741 sqlippool_command(data->alive_begin, sqlsocket, instance, request,
747 sqlippool_command(data->alive_update, sqlsocket, instance, request,
753 sqlippool_command(data->alive_commit, sqlsocket, instance, request,
756 sql_release_socket(data->sql_inst, sqlsocket);
758 return RLM_MODULE_OK;
761 static int sqlippool_accounting_stop(void * instance, REQUEST * request)
763 char logstr[MAX_STRING_LEN];
765 rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
768 if (pairfind(request->packet->vps, PW_NAS_PORT) == NULL) {
769 DEBUG("rlm_ippool: Could not find port number in packet.");
770 return RLM_MODULE_NOOP;
773 if (pairfind(request->packet->vps, PW_NAS_IP_ADDRESS) == NULL) {
774 DEBUG("rlm_ippool: Could not find nas information in packet.");
775 return RLM_MODULE_NOOP;
778 sqlsocket = sql_get_socket(data->sql_inst);
779 if (sqlsocket == NULL) {
780 DEBUG("rlm_sqlippool: cannot allocate sql connection");
781 return RLM_MODULE_NOOP;
787 sqlippool_command(data->stop_begin, sqlsocket, instance, request,
793 sqlippool_command(data->stop_clear, sqlsocket, instance, request,
799 sqlippool_command(data->stop_commit, sqlsocket, instance, request,
802 sql_release_socket(data->sql_inst, sqlsocket);
803 radius_xlat(logstr, sizeof(logstr), data->log_clear, request, NULL);
805 return do_logging(logstr, RLM_MODULE_OK);
808 static int sqlippool_accounting_on(void * instance, REQUEST * request)
810 rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
813 if (pairfind(request->packet->vps, PW_NAS_IP_ADDRESS) == NULL) {
814 DEBUG("rlm_ippool: Could not find nas information in packet.");
815 return RLM_MODULE_NOOP;
818 sqlsocket = sql_get_socket(data->sql_inst);
819 if (sqlsocket == NULL) {
820 DEBUG("rlm_sqlippool: cannot allocate sql connection");
821 return RLM_MODULE_NOOP;
827 sqlippool_command(data->on_begin, sqlsocket, instance, request,
833 sqlippool_command(data->on_clear, sqlsocket, instance, request,
839 sqlippool_command(data->on_commit, sqlsocket, instance, request,
842 sql_release_socket(data->sql_inst, sqlsocket);
844 return RLM_MODULE_OK;
847 static int sqlippool_accounting_off(void * instance, REQUEST * request)
849 rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
852 if (pairfind(request->packet->vps, PW_NAS_IP_ADDRESS) == NULL) {
853 DEBUG("rlm_ippool: Could not find nas information in packet.");
854 return RLM_MODULE_NOOP;
857 sqlsocket = sql_get_socket(data->sql_inst);
858 if (sqlsocket == NULL) {
859 DEBUG("rlm_sqlippool: cannot allocate sql connection");
860 return RLM_MODULE_NOOP;
866 sqlippool_command(data->off_begin, sqlsocket, instance, request,
872 sqlippool_command(data->off_clear, sqlsocket, instance, request,
878 sqlippool_command(data->off_commit, sqlsocket, instance, request,
881 sql_release_socket(data->sql_inst, sqlsocket);
883 return RLM_MODULE_OK;
887 * Check for an Accounting-Stop
888 * If we find one and we have allocated an IP to this nas/port combination, deallocate it.
890 static int sqlippool_accounting(void * instance, REQUEST * request)
893 int acct_status_type;
895 vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE);
897 DEBUG("rlm_sqlippool: Could not find account status type in packet.");
898 return RLM_MODULE_NOOP;
900 acct_status_type = vp->lvalue;
902 switch (acct_status_type) {
903 case PW_STATUS_START:
904 return sqlippool_accounting_start(instance, request);
906 case PW_STATUS_ALIVE:
907 return sqlippool_accounting_alive(instance, request);
910 return sqlippool_accounting_stop(instance, request);
912 case PW_STATUS_ACCOUNTING_ON:
913 return sqlippool_accounting_on(instance, request);
915 case PW_STATUS_ACCOUNTING_OFF:
916 return sqlippool_accounting_off(instance, request);
919 /* We don't care about any other accounting packet */
920 return RLM_MODULE_NOOP;
924 static int sqlippool_detach(void *instance)
926 rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
932 * The module name should be the only globally exported symbol.
933 * That is, everything else should be 'static'.
935 * If the module needs to temporarily modify it's instantiation
936 * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
937 * The server will then take care of ensuring that the module
938 * is single-threaded.
940 module_t rlm_sqlippool = {
943 RLM_TYPE_THREAD_SAFE, /* type */
944 sqlippool_instantiate, /* instantiation */
945 sqlippool_detach, /* detach */
947 NULL, /* authentication */
948 NULL, /* authorization */
949 NULL, /* preaccounting */
950 sqlippool_accounting, /* accounting */
951 NULL, /* checksimul */
952 NULL, /* pre-proxy */
953 NULL, /* post-proxy */
954 sqlippool_postauth /* post-auth */