2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 * @file rlm_sqlippool.c
20 * @brief Allocates an IPv4 address from pools stored in SQL.
22 * @copyright 2002 Globe.Net Communications Limited
23 * @copyright 2006 The FreeRADIUS server project
24 * @copyright 2006 Suntel Communications
28 #include <freeradius-devel/radiusd.h>
29 #include <freeradius-devel/rad_assert.h>
35 #define MAX_QUERY_LEN 4096
38 * Define a structure for our module configuration.
40 typedef struct rlm_sqlippool_t {
41 char const *sql_instance_name;
43 uint32_t lease_duration;
47 char const *pool_name;
48 bool ipv6; //!< Whether or not we do IPv6 pools.
49 int framed_ip_address; //!< the attribute number for Framed-IP(v6)-Address
51 time_t last_clear; //!< So we only do it once a second.
52 char const *allocate_begin; //!< SQL query to begin.
53 char const *allocate_clear; //!< SQL query to clear an IP.
54 char const *allocate_find; //!< SQL query to find an unused IP.
55 char const *allocate_update; //!< SQL query to mark an IP as used.
56 char const *allocate_commit; //!< SQL query to commit.
58 char const *pool_check; //!< Query to check for the existence of the pool.
61 char const *start_begin; //!< SQL query to begin.
62 char const *start_update; //!< SQL query to update an IP entry.
63 char const *start_commit; //!< SQL query to commit.
66 char const *alive_begin; //!< SQL query to begin.
67 char const *alive_update; //!< SQL query to update an IP entry.
68 char const *alive_commit; //!< SQL query to commit.
71 char const *stop_begin; //!< SQL query to begin.
72 char const *stop_clear; //!< SQL query to clear an IP.
73 char const *stop_commit; //!< SQL query to commit.
76 char const *on_begin; //!< SQL query to begin.
77 char const *on_clear; //!< SQL query to clear an entire NAS.
78 char const *on_commit; //!< SQL query to commit.
81 char const *off_begin; //!< SQL query to begin.
82 char const *off_clear; //!< SQL query to clear an entire NAS.
83 char const *off_commit; //!< SQL query to commit.
86 char const *log_exists; //!< There was an ip address already assigned.
87 char const *log_success; //!< We successfully allocated ip address from pool.
88 char const *log_clear; //!< We successfully deallocated ip address from pool.
89 char const *log_failed; //!< Failed to allocate ip from the pool.
90 char const *log_nopool; //!< There was no Framed-IP-Address but also no Pool-Name.
92 /* Reserved to handle 255.255.255.254 Requests */
93 char const *defaultpool; //!< Default Pool-Name if there is none in the check items.
97 static CONF_PARSER message_config[] = {
98 { "exists", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, log_exists), NULL },
99 { "success", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, log_success), NULL },
100 { "clear", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, log_clear), NULL },
101 { "failed", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, log_failed), NULL },
102 { "nopool", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, log_nopool), NULL },
104 { NULL, -1, 0, NULL, NULL }
108 * A mapping of configuration file names to internal variables.
110 * Note that the string is dynamically allocated, so it MUST
111 * be freed. When the configuration file parse re-reads the string,
112 * it free's the old one, and strdup's the new one, placing the pointer
113 * to the strdup'd string into 'config.string'. This gets around
116 static CONF_PARSER module_config[] = {
117 { "sql-instance-name", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_DEPRECATED, rlm_sqlippool_t, sql_instance_name), NULL },
118 { "sql_module_instance", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_REQUIRED, rlm_sqlippool_t, sql_instance_name), "sql" },
120 { "lease-duration", FR_CONF_OFFSET(PW_TYPE_INTEGER | PW_TYPE_DEPRECATED, rlm_sqlippool_t, lease_duration), NULL },
121 { "lease_duration", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_sqlippool_t, lease_duration), "86400" },
123 { "pool-name", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_DEPRECATED, rlm_sqlippool_t, pool_name), NULL },
124 { "pool_name", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_sqlippool_t, pool_name), "" },
126 { "default-pool", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_DEPRECATED, rlm_sqlippool_t, defaultpool), NULL },
127 { "default_pool", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_sqlippool_t, defaultpool), "main_pool" },
130 { "ipv6", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_sqlippool_t, ipv6), NULL},
132 { "allocate-begin", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, allocate_begin), NULL },
133 { "allocate_begin", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, allocate_begin), "START TRANSACTION" },
135 { "allocate-clear", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, allocate_clear), NULL },
136 { "allocate_clear", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_REQUIRED, rlm_sqlippool_t, allocate_clear), "" },
138 { "allocate-find", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, allocate_find), NULL },
139 { "allocate_find", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_REQUIRED, rlm_sqlippool_t, allocate_find), "" },
141 { "allocate-update", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, allocate_update), NULL },
142 { "allocate_update", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_REQUIRED, rlm_sqlippool_t, allocate_update), "" },
144 { "allocate-commit", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, allocate_commit), NULL },
145 { "allocate_commit", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, allocate_commit), "COMMIT" },
148 { "pool-check", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, pool_check), NULL },
149 { "pool_check", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, pool_check), "" },
152 { "start-begin", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, start_begin), NULL },
153 { "start_begin", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, start_begin), "START TRANSACTION" },
155 { "start-update", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, start_update), NULL },
156 { "start_update", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_REQUIRED, rlm_sqlippool_t, start_update), "" },
158 { "start-commit", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, start_commit), NULL },
159 { "start_commit", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, start_commit), "COMMIT" },
162 { "alive-begin", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, alive_begin), NULL },
163 { "alive_begin", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, alive_begin), "START TRANSACTION" },
165 { "alive-update", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, alive_update), NULL },
166 { "alive_update", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_REQUIRED, rlm_sqlippool_t, alive_update), "" },
168 { "alive-commit", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, alive_commit), NULL },
169 { "alive_commit", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, alive_commit), "COMMIT" },
172 { "stop-begin", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, stop_begin), NULL },
173 { "stop_begin", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, stop_begin), "START TRANSACTION" },
175 { "stop-clear", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, stop_clear), NULL },
176 { "stop_clear", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_REQUIRED, rlm_sqlippool_t, stop_clear), "" },
178 { "stop-commit", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, stop_commit), NULL },
179 { "stop_commit", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, stop_commit), "COMMIT" },
182 { "on-begin", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, on_begin), NULL },
183 { "on_begin", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, on_begin), "START TRANSACTION" },
185 { "on-clear", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, on_clear), NULL },
186 { "on_clear", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_REQUIRED, rlm_sqlippool_t, on_clear), "" },
188 { "on-commit", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, on_commit), NULL },
189 { "on_commit", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, on_commit), "COMMIT" },
192 { "off-begin", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, off_begin), NULL },
193 { "off_begin", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, off_begin), "START TRANSACTION" },
195 { "off-clear", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, off_clear), NULL },
196 { "off_clear", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_REQUIRED, rlm_sqlippool_t, off_clear), "" },
198 { "off-commit", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, off_commit), NULL },
199 { "off_commit", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, off_commit), "COMMIT" },
201 { "messages", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) message_config },
203 { NULL, -1, 0, NULL, NULL }
207 * Replace %<whatever> in a string.
214 static int sqlippool_expand(char * out, int outlen, char const * fmt,
215 rlm_sqlippool_t *data, char * param, int param_len)
219 char tmp[40]; /* For temporary storing of integers */
222 for (p = fmt; *p ; p++) {
226 /* Calculate freespace in output */
227 freespace = outlen - (q - out);
243 case 'P': /* pool name */
244 strlcpy(q, data->pool_name, freespace);
247 case 'I': /* IP address */
248 if (param && param_len > 0) {
249 if (param_len > freespace) {
250 strlcpy(q, param, freespace);
254 memcpy(q, param, param_len);
259 case 'J': /* lease duration */
260 sprintf(tmp, "%d", data->lease_duration);
261 strlcpy(q, tmp, freespace);
275 DEBUG2("sqlippool_expand: \"%s\"", out);
281 /** Perform a single sqlippool query
283 * Mostly wrapper around sql_query which does some special sqlippool sequence substitutions and expands
286 * @param fmt sql query to expand.
287 * @param handle sql connection handle.
288 * @param data Instance of rlm_sqlippool.
289 * @param request Current request.
290 * @param param ip address string.
291 * @param param_len ip address string len.
292 * @return 0 on success or < 0 on error.
294 static int sqlippool_command(char const * fmt, rlm_sql_handle_t * handle, rlm_sqlippool_t *data, REQUEST *request,
295 char *param, int param_len)
297 char query[MAX_QUERY_LEN];
298 char *expanded = NULL;
303 * If we don't have a command, do nothing.
308 * @todo this needs to die (should just be done in xlat expansion)
310 sqlippool_expand(query, sizeof(query), fmt, data, param, param_len);
312 if (radius_axlat(&expanded, request, query, data->sql_inst->sql_escape_func, data->sql_inst) < 0) {
316 ret = data->sql_inst->sql_query(data->sql_inst, request, &handle, expanded);
318 talloc_free(expanded);
321 talloc_free(expanded);
323 (data->sql_inst->module->sql_finish_query)(handle, data->sql_inst->config);
328 * Don't repeat yourself
331 #define DO(_x) sqlippool_command(inst->_x, handle, inst, request, NULL, 0)
334 * Query the database expecting a single result row
336 static int CC_HINT(nonnull (1, 3, 4, 5)) sqlippool_query1(char *out, int outlen, char const *fmt,
337 rlm_sql_handle_t *handle, rlm_sqlippool_t *data,
338 REQUEST *request, char *param, int param_len)
340 char query[MAX_QUERY_LEN];
341 char *expanded = NULL;
348 * @todo this needs to die (should just be done in xlat expansion)
350 sqlippool_expand(query, sizeof(query), fmt, data, param, param_len);
355 * Do an xlat on the provided string
357 if (radius_axlat(&expanded, request, query, data->sql_inst->sql_escape_func, data->sql_inst) < 0) {
360 retval = data->sql_inst->sql_select_query(data->sql_inst, request, &handle, expanded);
361 talloc_free(expanded);
364 REDEBUG("database query error on '%s'", query);
368 if (data->sql_inst->sql_fetch_row(&row, data->sql_inst, request, &handle) < 0) {
369 REDEBUG("Failed fetching query result");
374 REDEBUG("SQL query did not return any results");
379 REDEBUG("The first column of the result was NULL");
383 rlen = strlen(row[0]);
384 if (rlen >= outlen) {
385 RDEBUG("insufficient string space");
392 (data->sql_inst->module->sql_finish_select_query)(handle, data->sql_inst->config);
398 * Do any per-module initialization that is separate to each
399 * configured instance of the module. e.g. set up connections
400 * to external databases, read configuration files, set up
401 * dictionary entries, etc.
403 * If configuration information is given in the config section
404 * that must be referenced in later calls, store a handle to it
405 * in *instance otherwise put a null pointer there.
407 static int mod_instantiate(CONF_SECTION *conf, void *instance)
409 module_instance_t *sql_inst;
410 rlm_sqlippool_t *inst = instance;
411 char const *pool_name = NULL;
413 pool_name = cf_section_name2(conf);
414 if (pool_name != NULL) {
415 inst->pool_name = talloc_typed_strdup(inst, pool_name);
417 inst->pool_name = talloc_typed_strdup(inst, "ippool");
419 sql_inst = find_module_instance(cf_section_find("modules"),
420 inst->sql_instance_name, true);
422 cf_log_err_cs(conf, "failed to find sql instance named %s",
423 inst->sql_instance_name);
428 inst->framed_ip_address = PW_FRAMED_IP_ADDRESS;
430 inst->framed_ip_address = PW_FRAMED_IPV6_PREFIX;
433 if (strcmp(sql_inst->entry->name, "rlm_sql") != 0) {
434 cf_log_err_cs(conf, "Module \"%s\""
435 " is not an instance of the rlm_sql module",
436 inst->sql_instance_name);
440 inst->sql_inst = (rlm_sql_t *) sql_inst->insthandle;
446 * If we have something to log, then we log it.
447 * Otherwise we return the retcode as soon as possible
449 static int do_logging(REQUEST *request, char const *str, int rcode)
451 char *expanded = NULL;
453 if (!str || !*str) return rcode;
455 if (radius_axlat(&expanded, request, str, NULL, NULL) < 0) {
459 pairmake_config("Module-Success-Message", expanded, T_OP_SET);
461 talloc_free(expanded);
468 * Allocate an IP number from the pool.
470 static rlm_rcode_t CC_HINT(nonnull) mod_post_auth(void *instance, REQUEST *request)
472 rlm_sqlippool_t *inst = (rlm_sqlippool_t *) instance;
473 char allocation[MAX_STRING_LEN];
476 rlm_sql_handle_t *handle;
480 * If there is a Framed-IP-Address attribute in the reply do nothing
482 if (pairfind(request->reply->vps, inst->framed_ip_address, 0, TAG_ANY) != NULL) {
483 RDEBUG("Framed-IP-Address already exists");
485 return do_logging(request, inst->log_exists, RLM_MODULE_NOOP);
488 if (pairfind(request->config_items, PW_POOL_NAME, 0, TAG_ANY) == NULL) {
489 RDEBUG("No Pool-Name defined");
491 return do_logging(request, inst->log_nopool, RLM_MODULE_NOOP);
494 handle = fr_connection_get(inst->sql_inst->pool);
496 REDEBUG("cannot get sql connection");
497 return RLM_MODULE_FAIL;
500 if (inst->sql_inst->sql_set_user(inst->sql_inst, request, NULL) < 0) {
501 return RLM_MODULE_FAIL;
505 * Limit the number of clears we do. There are minor
506 * race conditions for the check, but so what. The
507 * actual work is protected by a transaction. The idea
508 * here is that if we're allocating 100 IPs a second,
509 * we're only do 1 CLEAR per second.
512 if (inst->last_clear < now) {
513 inst->last_clear = now;
522 allocation_len = sqlippool_query1(allocation, sizeof(allocation),
523 inst->allocate_find, handle,
524 inst, request, (char *) NULL, 0);
529 if (allocation_len == 0) {
533 *Should we perform pool-check ?
535 if (inst->pool_check && *inst->pool_check) {
538 *Ok, so the allocate-find query found nothing ...
539 *Let's check if the pool exists at all
541 allocation_len = sqlippool_query1(allocation, sizeof(allocation),
542 inst->pool_check, handle, inst, request,
545 fr_connection_release(inst->sql_inst->pool, handle);
547 if (allocation_len) {
550 * Pool exists after all... So,
551 * the failure to allocate the IP
552 * address was most likely due to
553 * the depletion of the pool. In
554 * that case, we should return
557 RDEBUG("pool appears to be full");
558 return do_logging(request, inst->log_failed, RLM_MODULE_NOTFOUND);
563 * Pool doesn't exist in the table. It
564 * may be handled by some other instance of
565 * sqlippool, so we should just ignore this
566 * allocation failure and return NOOP
568 RDEBUG("IP address could not be allocated as no pool exists with that name");
569 return RLM_MODULE_NOOP;
573 fr_connection_release(inst->sql_inst->pool, handle);
575 RDEBUG("IP address could not be allocated");
576 return do_logging(request, inst->log_failed, RLM_MODULE_NOOP);
580 * See if we can create the VP from the returned data. If not,
581 * error out. If so, add it to the list.
583 vp = paircreate(request->reply, inst->framed_ip_address, 0);
584 if (pairparsevalue(vp, allocation, allocation_len) < 0) {
587 RDEBUG("Invalid IP number [%s] returned from instbase query.", allocation);
588 fr_connection_release(inst->sql_inst->pool, handle);
589 return do_logging(request, inst->log_failed, RLM_MODULE_NOOP);
592 RDEBUG("Allocated IP %s", allocation);
593 pairadd(&request->reply->vps, vp);
598 sqlippool_command(inst->allocate_update, handle, inst, request,
599 allocation, allocation_len);
603 fr_connection_release(inst->sql_inst->pool, handle);
605 return do_logging(request, inst->log_success, RLM_MODULE_OK);
608 static int mod_accounting_start(rlm_sql_handle_t *handle,
609 rlm_sqlippool_t *inst, REQUEST *request)
615 return RLM_MODULE_OK;
618 static int mod_accounting_alive(rlm_sql_handle_t *handle,
619 rlm_sqlippool_t *inst, REQUEST *request)
624 return RLM_MODULE_OK;
627 static int mod_accounting_stop(rlm_sql_handle_t *handle,
628 rlm_sqlippool_t *inst, REQUEST *request)
634 return do_logging(request, inst->log_clear, RLM_MODULE_OK);
637 static int mod_accounting_on(rlm_sql_handle_t *handle,
638 rlm_sqlippool_t *inst, REQUEST *request)
644 return RLM_MODULE_OK;
647 static int mod_accounting_off(rlm_sql_handle_t *handle,
648 rlm_sqlippool_t *inst, REQUEST *request)
654 return RLM_MODULE_OK;
658 * Check for an Accounting-Stop
659 * If we find one and we have allocated an IP to this nas/port
660 * combination, then deallocate it.
662 static rlm_rcode_t CC_HINT(nonnull) mod_accounting(void *instance, REQUEST *request)
664 int rcode = RLM_MODULE_NOOP;
666 int acct_status_type;
667 rlm_sqlippool_t *inst = (rlm_sqlippool_t *) instance;
668 rlm_sql_handle_t *handle;
670 vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE, 0, TAG_ANY);
672 RDEBUG("Could not find account status type in packet");
673 return RLM_MODULE_NOOP;
675 acct_status_type = vp->vp_integer;
677 switch (acct_status_type) {
678 case PW_STATUS_START:
679 case PW_STATUS_ALIVE:
681 case PW_STATUS_ACCOUNTING_ON:
682 case PW_STATUS_ACCOUNTING_OFF:
683 break; /* continue through to the next section */
686 /* We don't care about any other accounting packet */
687 return RLM_MODULE_NOOP;
690 handle = fr_connection_get(inst->sql_inst->pool);
692 RDEBUG("Cannot allocate sql connection");
693 return RLM_MODULE_FAIL;
696 if (inst->sql_inst->sql_set_user(inst->sql_inst, request, NULL) < 0) {
697 return RLM_MODULE_FAIL;
700 switch (acct_status_type) {
701 case PW_STATUS_START:
702 rcode = mod_accounting_start(handle, inst, request);
705 case PW_STATUS_ALIVE:
706 rcode = mod_accounting_alive(handle, inst, request);
710 rcode = mod_accounting_stop(handle, inst, request);
713 case PW_STATUS_ACCOUNTING_ON:
714 rcode = mod_accounting_on(handle, inst, request);
717 case PW_STATUS_ACCOUNTING_OFF:
718 rcode = mod_accounting_off(handle, inst, request);
722 fr_connection_release(inst->sql_inst->pool, handle);
728 * The module name should be the only globally exported symbol.
729 * That is, everything else should be 'static'.
731 * If the module needs to temporarily modify it's instantiation
732 * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
733 * The server will then take care of ensuring that the module
734 * is single-threaded.
736 extern module_t rlm_sqlippool;
737 module_t rlm_sqlippool = {
740 RLM_TYPE_THREAD_SAFE, /* type */
741 sizeof(rlm_sqlippool_t),
743 mod_instantiate, /* instantiation */
746 NULL, /* authentication */
747 NULL, /* authorization */
748 NULL, /* preaccounting */
749 mod_accounting, /* accounting */
750 NULL, /* checksimul */
751 NULL, /* pre-proxy */
752 NULL, /* post-proxy */
753 mod_post_auth /* post-auth */