rlm_redis argument splitting
[freeradius.git] / src / modules / rlm_redis / rlm_redis.c
index 695d724..3776c52 100644 (file)
@@ -1,12 +1,7 @@
 /*
- * rlm_redis.c
- *
- * 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 is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License, version 2 if the
+ *   License as published by the Free Software Foundation.
  *
  *   This program is distributed in the hope that it will be useful,
  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  *   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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+/**
+ * $Id$
+ * @file rlm_redis.c
+ * @brief Driver for the REDIS noSQL key value stores.
  *
- * Copyright 2000,2006  The FreeRADIUS server project
- * Copyright 2011  TekSavvy Solutions <gabe@teksavvy.com>
+ * @copyright 2000,2006  The FreeRADIUS server project
+ * @copyright 2011  TekSavvy Solutions <gabe@teksavvy.com>
  */
-
 #include <freeradius-devel/ident.h>
 
 RCSID("$Id$")
@@ -66,14 +66,14 @@ static void *redis_create_conn(void *ctx)
        char buffer[1024];
 
        conn = redisConnect(inst->hostname, inst->port);
-       if (dissocket->conn->err) return NULL;
+       if (conn->err) return NULL;
 
        if (inst->password) {
                redisReply *reply = NULL;
 
                snprintf(buffer, sizeof(buffer), "AUTH %s", inst->password);
 
-               reply = redisCommand(dissocket->conn, buffer);
+               reply = redisCommand(conn, buffer);
                if (!reply) {
                        radlog(L_ERR, "rlm_redis (%s): Failed to run AUTH",
                               inst->xlat_name);
@@ -88,7 +88,7 @@ static void *redis_create_conn(void *ctx)
                case REDIS_REPLY_STATUS:
                        if (strcmp(reply->str, "OK") != 0) {
                                radlog(L_ERR, "rlm_redis (%s): Failed authentication: reply %s",
-                                      inst->xlat_name, dissocket->reply->str);
+                                      inst->xlat_name, reply->str);
                                goto do_close;
                        }
                        break;  /* else it's OK */
@@ -105,7 +105,7 @@ static void *redis_create_conn(void *ctx)
 
                snprintf(buffer, sizeof(buffer), "SELECT %d", inst->database);
 
-               reply = redisCommand(dissocket->conn, buffer);
+               reply = redisCommand(conn, buffer);
                if (!reply) {
                        radlog(L_ERR, "rlm_redis (%s): Failed to run SELECT",
                               inst->xlat_name);
@@ -118,7 +118,7 @@ static void *redis_create_conn(void *ctx)
                        if (strcmp(reply->str, "OK") != 0) {
                                radlog(L_ERR, "rlm_redis (%s): Failed SELECT %d: reply %s",
                                       inst->xlat_name, inst->database,
-                                      dissocket->reply->str);
+                                      reply->str);
                                goto do_close;
                        }
                        break;  /* else it's OK */
@@ -193,15 +193,6 @@ static size_t redis_xlat(void *instance, REQUEST *request,
        size_t ret = 0;
        char *buffer_ptr;
        char buffer[21];
-       char querystr[MAX_QUERY_LEN];
-
-       if (!radius_xlat(querystr, sizeof(querystr), fmt, request,
-                   redis_escape_func, inst)) {
-               radlog(L_ERR, "rlm_redis (%s): xlat failed.",
-                      inst->xlat_name);
-
-               return 0;
-       }
 
        dissocket = fr_connection_get(inst->pool);
        if (!dissocket) {
@@ -212,7 +203,7 @@ static size_t redis_xlat(void *instance, REQUEST *request,
        }
 
        /* Query failed for some reason, release socket and return */
-       if (rlm_redis_query(&dissocket, inst, querystr) < 0) {
+       if (rlm_redis_query(&dissocket, inst, fmt, request) < 0) {
                goto release;
        }
 
@@ -264,10 +255,7 @@ static int redis_detach(void *instance)
 
        if (inst->xlat_name) {
                xlat_unregister(inst->xlat_name, redis_xlat, instance);
-               free(inst->xlat_name);
        }
-       free(inst->xlat_name);
-       free(inst);
 
        return 0;
 }
@@ -275,18 +263,27 @@ static int redis_detach(void *instance)
 /*
  *     Query the redis database
  */
-int rlm_redis_query(REDISSOCK **dissocket_p, REDIS_INST *inst, char *query)
+int rlm_redis_query(REDISSOCK **dissocket_p, REDIS_INST *inst,
+                   const char *query, REQUEST *request)
 {
        REDISSOCK *dissocket;
+       int argc;
+       const char *argv[MAX_REDIS_ARGS];
+       char argv_buf[MAX_QUERY_LEN];
 
        if (!query || !*query || !inst || !dissocket_p) {
                return -1;
        }
 
+       argc = rad_expand_xlat(request, query, MAX_REDIS_ARGS, argv, 0,
+                               sizeof(argv_buf), argv_buf);
+       if (argc <= 0)
+               return -1;
+
        dissocket = *dissocket_p;
 
-       DEBUG2("executing query %s", query);
-       dissocket->reply = redisCommand(dissocket->conn, query);
+       DEBUG2("executing %s ...", argv[0]);
+       dissocket->reply = redisCommandArgv(dissocket->conn, argc, argv, NULL);
 
        if (!dissocket->reply) {
                radlog(L_ERR, "rlm_redis: (%s) REDIS error: %s",
@@ -313,10 +310,6 @@ int rlm_redis_query(REDISSOCK **dissocket_p, REDIS_INST *inst, char *query)
        if (dissocket->reply->type == REDIS_REPLY_ERROR) {
                radlog(L_ERR, "rlm_redis (%s): query failed, %s",
                       inst->xlat_name, query);
-
-               /* Free the reply just in case */
-               rlm_redis_finish_query(dissocket);
-
                return -1;
        }
 
@@ -345,18 +338,14 @@ static int redis_instantiate(CONF_SECTION *conf, void **instance)
        /*
         *      Set up a storage area for instance data
         */
-       inst = rad_malloc(sizeof (REDIS_INST));
-       if (!inst) {
-               return -1;
-       }
-       memset(inst, 0, sizeof (*inst));
+       *instance = inst = talloc_zero(conf, REDIS_INST);
+       if (!inst) return -1;
 
        /*
         *      If the configuration parameters can't be parsed, then
         *      fail.
         */
        if (cf_section_parse(conf, inst, module_config) < 0) {
-               free(inst);
                return -1;
        }
 
@@ -365,14 +354,12 @@ static int redis_instantiate(CONF_SECTION *conf, void **instance)
        if (!xlat_name)
                xlat_name = cf_section_name1(conf);
 
-       inst->xlat_name = strdup(xlat_name);
        xlat_register(inst->xlat_name, redis_xlat, inst);
 
        inst->pool = fr_connection_pool_init(conf, inst,
                                             redis_create_conn, NULL,
                                             redis_delete_conn);
        if (!inst->pool) {
-               redis_detach(inst);
                return -1;
        }
 
@@ -380,8 +367,6 @@ static int redis_instantiate(CONF_SECTION *conf, void **instance)
        inst->redis_finish_query = rlm_redis_finish_query;
        inst->redis_escape_func = redis_escape_func;
 
-       *instance = inst;
-
        return 0;
 }