Allow sqlite filename to be specified in the configuration file.
[freeradius.git] / src / modules / rlm_sql / rlm_sql.c
index babcc8e..15da1c6 100644 (file)
 #include <freeradius-devel/ident.h>
 RCSID("$Id$")
 
-#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/rad_assert.h>
 
-#include <stdio.h>
 #include <sys/stat.h>
-#include <stdlib.h>
 
-#include <time.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <string.h>
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <freeradius-devel/radiusd.h>
-#include <freeradius-devel/modules.h>
 #include "rlm_sql.h"
-#include <freeradius-devel/rad_assert.h>
 
 static char *allowed_chars = NULL;
 
@@ -62,6 +49,10 @@ static const CONF_PARSER module_config[] = {
         offsetof(SQL_CONFIG,sql_password), NULL, ""},
        {"radius_db", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,sql_db), NULL, "radius"},
+       {"filename", PW_TYPE_FILENAME, /* for sqlite */
+        offsetof(SQL_CONFIG,sql_file), NULL, NULL},
+       {"read_groups", PW_TYPE_BOOLEAN,
+        offsetof(SQL_CONFIG,read_groups), NULL, "yes"},
        {"sqltrace", PW_TYPE_BOOLEAN,
         offsetof(SQL_CONFIG,sqltrace), NULL, "no"},
        {"sqltracefile", PW_TYPE_STRING_PTR,
@@ -72,6 +63,10 @@ static const CONF_PARSER module_config[] = {
         offsetof(SQL_CONFIG,deletestalesessions), NULL, "yes"},
        {"num_sql_socks", PW_TYPE_INTEGER,
         offsetof(SQL_CONFIG,num_sql_socks), NULL, "5"},
+       {"lifetime", PW_TYPE_INTEGER,
+        offsetof(SQL_CONFIG,lifetime), NULL, "0"},
+       {"max_queries", PW_TYPE_INTEGER,
+        offsetof(SQL_CONFIG,max_queries), NULL, "0"},
        {"sql_user_name", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,query_user), NULL, ""},
        {"default_user_profile", PW_TYPE_STRING_PTR,
@@ -81,7 +76,7 @@ static const CONF_PARSER module_config[] = {
        {"authorize_check_query", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,authorize_check_query), NULL, ""},
        {"authorize_reply_query", PW_TYPE_STRING_PTR,
-        offsetof(SQL_CONFIG,authorize_reply_query), NULL, ""},
+        offsetof(SQL_CONFIG,authorize_reply_query), NULL, NULL},
        {"authorize_group_check_query", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,authorize_group_check_query), NULL, ""},
        {"authorize_group_reply_query", PW_TYPE_STRING_PTR,
@@ -101,7 +96,7 @@ static const CONF_PARSER module_config[] = {
        {"accounting_stop_query_alt", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,accounting_stop_query_alt), NULL, ""},
        {"group_membership_query", PW_TYPE_STRING_PTR,
-        offsetof(SQL_CONFIG,groupmemb_query), NULL, ""},
+        offsetof(SQL_CONFIG,groupmemb_query), NULL, NULL},
        {"connect_failure_retry_delay", PW_TYPE_INTEGER,
         offsetof(SQL_CONFIG,connect_failure_retry_delay), NULL, "60"},
        {"simul_count_query", PW_TYPE_STRING_PTR,
@@ -114,6 +109,12 @@ static const CONF_PARSER module_config[] = {
         offsetof(SQL_CONFIG,allowed_chars), NULL,
        "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"},
 
+       /*
+        *      This only works for a few drivers.
+        */
+       {"query_timeout", PW_TYPE_INTEGER,
+        offsetof(SQL_CONFIG,query_timeout), NULL, NULL},
+        
        {NULL, -1, 0, NULL, NULL}
 };
 
@@ -123,9 +124,9 @@ static const CONF_PARSER module_config[] = {
 static int fallthrough(VALUE_PAIR *vp)
 {
        VALUE_PAIR *tmp;
-       tmp = pairfind(vp, PW_FALL_THROUGH);
+       tmp = pairfind(vp, PW_FALL_THROUGH, 0);
 
-       return tmp ? tmp->lvalue : 0;
+       return tmp ? tmp->vp_integer : 0;
 }
 
 
@@ -133,13 +134,15 @@ static int fallthrough(VALUE_PAIR *vp)
 /*
  *     Yucky prototype.
  */
-static int sql_set_user(SQL_INST *inst, REQUEST *request, char *sqlusername, const char *username);
 static int generate_sql_clients(SQL_INST *inst);
-static int sql_escape_func(char *out, int outlen, const char *in);
+static size_t sql_escape_func(char *out, size_t outlen, const char *in);
 
 /*
  *     sql xlat function. Right now only SELECTs are supported. Only
  *     the first element of the SELECT result will be used.
+ *
+ *     For other statements (insert, update, delete, etc.), the
+ *     number of affected rows will be returned.
  */
 static int sql_xlat(void *instance, REQUEST *request,
                    char *fmt, char *out, size_t freespace,
@@ -150,9 +153,10 @@ static int sql_xlat(void *instance, REQUEST *request,
        SQL_INST *inst = instance;
        char querystr[MAX_QUERY_LEN];
        char sqlusername[MAX_STRING_LEN];
-       int ret = 0;
+       size_t ret = 0;
+
+       RDEBUG("sql_xlat");
 
-       DEBUG("rlm_sql (%s): - sql_xlat", inst->config->xlat_name);
        /*
          * Add SQL-User-Name attribute just in case it is needed
          *  We could search the string fmt for SQL-User-Name to see if this is
@@ -172,10 +176,63 @@ static int sql_xlat(void *instance, REQUEST *request,
        sqlsocket = sql_get_socket(inst);
        if (sqlsocket == NULL)
                return 0;
+
+       /*
+        *      If the query starts with any of the following prefixes,
+        *      then return the number of rows affected
+        */
+       if ((strncasecmp(querystr, "insert", 6) == 0) ||
+           (strncasecmp(querystr, "update", 6) == 0) ||
+           (strncasecmp(querystr, "delete", 6) == 0)) {
+               int numaffected;
+               char buffer[21]; /* 64bit max is 20 decimal chars + null byte */
+
+               if (rlm_sql_query(sqlsocket,inst,querystr)) {
+                       radlog(L_ERR, "rlm_sql (%s): database query error, %s: %s",
+                               inst->config->xlat_name, querystr,
+                               (inst->module->sql_error)(sqlsocket,
+                                                         inst->config));
+                       sql_release_socket(inst,sqlsocket);
+                       return 0;
+               }
+              
+               numaffected = (inst->module->sql_affected_rows)(sqlsocket,
+                                                               inst->config);
+               if (numaffected < 1) {
+                       RDEBUG("rlm_sql (%s): SQL query affected no rows",
+                               inst->config->xlat_name);
+               }
+
+               /*
+                *      Don't chop the returned number if freespace is
+                *      too small.  This hack is necessary because
+                *      some implementations of snprintf return the
+                *      size of the written data, and others return
+                *      the size of the data they *would* have written
+                *      if the output buffer was large enough.
+                */
+               snprintf(buffer, sizeof(buffer), "%d", numaffected);
+               ret = strlen(buffer);
+               if (ret >= freespace){
+                       RDEBUG("rlm_sql (%s): Can't write result, insufficient string space",
+                              inst->config->xlat_name);
+                       (inst->module->sql_finish_query)(sqlsocket,
+                                                        inst->config);
+                       sql_release_socket(inst,sqlsocket);
+                       return 0;
+               }
+               
+               memcpy(out, buffer, ret + 1); /* we did bounds checking above */
+
+               (inst->module->sql_finish_query)(sqlsocket, inst->config);
+               sql_release_socket(inst,sqlsocket);
+               return ret;
+       } /* else it's a SELECT statement */
+
        if (rlm_sql_select_query(sqlsocket,inst,querystr)){
                radlog(L_ERR, "rlm_sql (%s): database query error, %s: %s",
                       inst->config->xlat_name,querystr,
-                      (char *)(inst->module->sql_error)(sqlsocket, inst->config));
+                      (inst->module->sql_error)(sqlsocket, inst->config));
                sql_release_socket(inst,sqlsocket);
                return 0;
        }
@@ -183,8 +240,7 @@ static int sql_xlat(void *instance, REQUEST *request,
        ret = rlm_sql_fetch_row(sqlsocket, inst);
 
        if (ret) {
-               DEBUG("rlm_sql (%s): SQL query did not succeed",
-                     inst->config->xlat_name);
+               RDEBUG("SQL query did not succeed");
                (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
                sql_release_socket(inst,sqlsocket);
                return 0;
@@ -192,33 +248,29 @@ static int sql_xlat(void *instance, REQUEST *request,
 
        row = sqlsocket->row;
        if (row == NULL) {
-               DEBUG("rlm_sql (%s): SQL query did not return any results",
-                     inst->config->xlat_name);
+               RDEBUG("SQL query did not return any results");
                (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
                sql_release_socket(inst,sqlsocket);
                return 0;
        }
 
        if (row[0] == NULL){
-               DEBUG("rlm_sql (%s): row[0] returned NULL",
-                     inst->config->xlat_name);
+               RDEBUG("row[0] returned NULL");
                (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
                sql_release_socket(inst,sqlsocket);
                return 0;
        }
        ret = strlen(row[0]);
-       if (ret > freespace){
-               DEBUG("rlm_sql (%s): sql_xlat:: Insufficient string space",
-                     inst->config->xlat_name);
+       if (ret >= freespace){
+               RDEBUG("Insufficient string space");
                (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
                sql_release_socket(inst,sqlsocket);
                return 0;
        }
 
-       strlcpy(out,row[0],ret);
+       strlcpy(out,row[0],freespace);
 
-       DEBUG("rlm_sql (%s): - sql_xlat finished",
-             inst->config->xlat_name);
+       RDEBUG("sql_xlat finished");
 
        (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
        sql_release_socket(inst,sqlsocket);
@@ -233,6 +285,7 @@ static int generate_sql_clients(SQL_INST *inst)
        RADCLIENT *c;
        char *prefix_ptr = NULL;
        unsigned int i = 0;
+       int numf = 0;
 
        DEBUG("rlm_sql (%s): Processing generate_sql_clients",
              inst->config->xlat_name);
@@ -247,8 +300,8 @@ static int generate_sql_clients(SQL_INST *inst)
                return -1;
        if (rlm_sql_select_query(sqlsocket,inst,querystr)){
                radlog(L_ERR, "rlm_sql (%s): database query error, %s: %s",
-                       inst->config->xlat_name,querystr,
-                       (char *)(inst->module->sql_error)(sqlsocket, inst->config));
+                      inst->config->xlat_name,querystr,
+                      (inst->module->sql_error)(sqlsocket, inst->config));
                sql_release_socket(inst,sqlsocket);
                return -1;
        }
@@ -266,6 +319,7 @@ static int generate_sql_clients(SQL_INST *inst)
         *  2. Shortname
         *  3. Type
         *  4. Secret
+        *  5. Virtual Server (optional)
         */
                if (!row[0]){
                        radlog(L_ERR, "rlm_sql (%s): No row id found on pass %d",inst->config->xlat_name,i);
@@ -287,8 +341,12 @@ static int generate_sql_clients(SQL_INST *inst)
                DEBUG("rlm_sql (%s): Read entry nasname=%s,shortname=%s,secret=%s",inst->config->xlat_name,
                        row[1],row[2],row[4]);
 
-               c = rad_malloc(sizeof(RADCLIENT));
-               memset(c, 0, sizeof(RADCLIENT));
+               c = rad_malloc(sizeof(*c));
+               memset(c, 0, sizeof(*c));
+
+#ifdef WITH_DYNAMIC_CLIENTS
+               c->dynamic = 1;
+#endif
 
                /*
                 *      Look for prefixes
@@ -313,7 +371,7 @@ static int generate_sql_clients(SQL_INST *inst)
                if (ip_hton(row[1], AF_UNSPEC, &c->ipaddr) < 0) {
                        radlog(L_CONS|L_ERR, "rlm_sql (%s): Failed to look up hostname %s: %s",
                               inst->config->xlat_name,
-                              row[1], librad_errstr);
+                              row[1], fr_strerror());
                        free(c);
                        continue;
                } else {
@@ -334,17 +392,24 @@ static int generate_sql_clients(SQL_INST *inst)
                }
 
                /*
-                *      Other values (secret, shortname, nastype)
+                *      Other values (secret, shortname, nastype, virtual_server)
                 */
-               c->secret = (u_char *)strdup(row[4]);
+               c->secret = strdup(row[4]);
                c->shortname = strdup(row[2]);
                if(row[3] != NULL)
                        c->nastype = strdup(row[3]);
 
-               DEBUG("rlm_sql (%s): Adding client %s (%s) to clients list",
+               numf = (inst->module->sql_num_fields)(sqlsocket, inst->config);
+               if ((numf > 5) && (row[5] != NULL) && *row[5]) c->server = strdup(row[5]);
+
+               DEBUG("rlm_sql (%s): Adding client %s (%s, server=%s) to clients list",
                      inst->config->xlat_name,
-                     c->longname,c->shortname);
-               if (!client_add(mainconfig.clients, c)) {
+                     c->longname,c->shortname, c->server ? c->server : "<none>");
+               if (!client_add(NULL, c)) {
+                       sql_release_socket(inst, sqlsocket);
+                       DEBUG("rlm_sql (%s): Failed to add client %s (%s) to clients list.  Maybe there's a duplicate?",
+                             inst->config->xlat_name,
+                             c->longname,c->shortname);
                        client_free(c);
                        return -1;
                }
@@ -359,9 +424,9 @@ static int generate_sql_clients(SQL_INST *inst)
 /*
  *     Translate the SQL queries.
  */
-static int sql_escape_func(char *out, int outlen, const char *in)
+static size_t sql_escape_func(char *out, size_t outlen, const char *in)
 {
-       int len = 0;
+       size_t len = 0;
 
        while (in[0]) {
                /*
@@ -413,7 +478,7 @@ static int sql_escape_func(char *out, int outlen, const char *in)
  *     escape it twice. (it will make things wrong if we have an
  *     escape candidate character in the username)
  */
-static int sql_set_user(SQL_INST *inst, REQUEST *request, char *sqlusername, const char *username)
+int sql_set_user(SQL_INST *inst, REQUEST *request, char *sqlusername, const char *username)
 {
        VALUE_PAIR *vp=NULL;
        char tmpuser[MAX_STRING_LEN];
@@ -422,10 +487,10 @@ static int sql_set_user(SQL_INST *inst, REQUEST *request, char *sqlusername, con
        sqlusername[0]= '\0';
 
        /* Remove any user attr we added previously */
-       pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+       pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
 
        if (username != NULL) {
-               strlcpy(tmpuser, username, MAX_STRING_LEN);
+               strlcpy(tmpuser, username, sizeof(tmpuser));
        } else if (strlen(inst->config->query_user)) {
                radius_xlat(tmpuser, sizeof(tmpuser), inst->config->query_user, request, NULL);
        } else {
@@ -433,15 +498,17 @@ static int sql_set_user(SQL_INST *inst, REQUEST *request, char *sqlusername, con
        }
 
        strlcpy(sqlusername, tmpuser, MAX_STRING_LEN);
-       DEBUG2("rlm_sql (%s): sql_set_user escaped user --> '%s'",
-                      inst->config->xlat_name, sqlusername);
-       vp = pairmake("SQL-User-Name", sqlusername, 0);
-       if (vp == NULL) {
-               radlog(L_ERR, "%s", librad_errstr);
+       RDEBUG2("sql_set_user escaped user --> '%s'", sqlusername);
+       vp = radius_pairmake(request, &request->packet->vps,
+                            "SQL-User-Name", NULL, 0);
+       if (!vp) {
+               radlog(L_ERR, "%s", fr_strerror());
                return -1;
        }
 
-       pairadd(&request->packet->vps, vp);
+       strlcpy(vp->vp_strvalue, tmpuser, sizeof(vp->vp_strvalue));
+       vp->length = strlen(vp->vp_strvalue);
+
        return 0;
 
 }
@@ -470,19 +537,21 @@ static int sql_get_grouplist (SQL_INST *inst, SQLSOCK *sqlsocket, REQUEST *reque
 
        group_list_tmp = *group_list = NULL;
 
-       if (inst->config->groupmemb_query[0] == 0)
-               return 1;
+       if (!inst->config->groupmemb_query ||
+           (inst->config->groupmemb_query[0] == 0))
+               return 0;
 
        if (!radius_xlat(querystr, sizeof(querystr), inst->config->groupmemb_query, request, sql_escape_func)) {
-               radlog(L_ERR, "rlm_sql (%s): xlat failed.",
-                       inst->config->xlat_name);
+               radlog_request(L_ERR, 0, request, "xlat \"%s\" failed.",
+                              inst->config->groupmemb_query);
                return -1;
        }
 
        if (rlm_sql_select_query(sqlsocket, inst, querystr) < 0) {
-               radlog(L_ERR, "rlm_sql (%s): database query error, %s: %s",
-                       inst->config->xlat_name,querystr,
-                       (char *)(inst->module->sql_error)(sqlsocket,inst->config));
+               radlog_request(L_ERR, 0, request,
+                              "database query error, %s: %s",
+                              querystr,
+                      (inst->module->sql_error)(sqlsocket,inst->config));
                return -1;
        }
        while (rlm_sql_fetch_row(sqlsocket, inst) == 0) {
@@ -490,8 +559,7 @@ static int sql_get_grouplist (SQL_INST *inst, SQLSOCK *sqlsocket, REQUEST *reque
                if (row == NULL)
                        break;
                if (row[0] == NULL){
-                       DEBUG("rlm_sql (%s): row[0] returned NULL",
-                               inst->config->xlat_name);
+                       RDEBUG("row[0] returned NULL");
                        (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
                        sql_grouplist_free(group_list);
                        return -1;
@@ -500,6 +568,7 @@ static int sql_get_grouplist (SQL_INST *inst, SQLSOCK *sqlsocket, REQUEST *reque
                        *group_list = rad_malloc(sizeof(SQL_GROUPLIST));
                        group_list_tmp = *group_list;
                } else {
+                       rad_assert(group_list_tmp != NULL);
                        group_list_tmp->next = rad_malloc(sizeof(SQL_GROUPLIST));
                        group_list_tmp = group_list_tmp->next;
                }
@@ -520,7 +589,7 @@ static int sql_get_grouplist (SQL_INST *inst, SQLSOCK *sqlsocket, REQUEST *reque
  * username will then be checked with the passed check string.
  */
 
-static int sql_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check,
+static int sql_groupcmp(void *instance, REQUEST *request, VALUE_PAIR *request_vp, VALUE_PAIR *check,
                        VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
 {
        SQLSOCK *sqlsocket;
@@ -530,23 +599,21 @@ static int sql_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE
 
        check_pairs = check_pairs;
        reply_pairs = reply_pairs;
-       request = request;
+       request_vp = request_vp;
 
-       DEBUG("rlm_sql (%s): - sql_groupcmp", inst->config->xlat_name);
+       RDEBUG("sql_groupcmp");
        if (!check || !check->vp_strvalue || !check->length){
-               DEBUG("rlm_sql (%s): sql_groupcmp: Illegal group name",
-                     inst->config->xlat_name);
+               RDEBUG("sql_groupcmp: Illegal group name");
                return 1;
        }
-       if (req == NULL){
-               DEBUG("rlm_sql (%s): sql_groupcmp: NULL request",
-                     inst->config->xlat_name);
+       if (!request){
+               RDEBUG("sql_groupcmp: NULL request");
                return 1;
        }
        /*
         * Set, escape, and check the user attr here
         */
-       if (sql_set_user(inst, req, sqlusername, NULL) < 0)
+       if (sql_set_user(inst, request, sqlusername, NULL) < 0)
                return 1;
 
        /*
@@ -555,31 +622,30 @@ static int sql_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE
        sqlsocket = sql_get_socket(inst);
        if (sqlsocket == NULL) {
                /* Remove the username we (maybe) added above */
-               pairdelete(&req->packet->vps, PW_SQL_USER_NAME);
+               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                return 1;
        }
 
        /*
         *      Get the list of groups this user is a member of
         */
-       if (sql_get_grouplist(inst, sqlsocket, req, &group_list)) {
-               radlog(L_ERR, "rlm_sql (%s): Error getting group membership",
-                      inst->config->xlat_name);
+       if (sql_get_grouplist(inst, sqlsocket, request, &group_list) < 0) {
+               radlog_request(L_ERR, 0, request,
+                              "Error getting group membership");
                /* Remove the username we (maybe) added above */
-               pairdelete(&req->packet->vps, PW_SQL_USER_NAME);
+               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                sql_release_socket(inst, sqlsocket);
                return 1;
        }
 
        for (group_list_tmp = group_list; group_list_tmp != NULL; group_list_tmp = group_list_tmp->next) {
                if (strcmp(group_list_tmp->groupname, check->vp_strvalue) == 0){
-                       DEBUG("rlm_sql (%s): - sql_groupcmp finished: User is a member of group %s",
-                             inst->config->xlat_name,
-                             (char *)check->vp_strvalue);
+                       RDEBUG("sql_groupcmp finished: User is a member of group %s",
+                              check->vp_strvalue);
                        /* Free the grouplist */
                        sql_grouplist_free(&group_list);
                        /* Remove the username we (maybe) added above */
-                       pairdelete(&req->packet->vps, PW_SQL_USER_NAME);
+                       pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                        sql_release_socket(inst, sqlsocket);
                        return 0;
                }
@@ -588,11 +654,11 @@ static int sql_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE
        /* Free the grouplist */
        sql_grouplist_free(&group_list);
        /* Remove the username we (maybe) added above */
-       pairdelete(&req->packet->vps, PW_SQL_USER_NAME);
+       pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
        sql_release_socket(inst,sqlsocket);
 
-       DEBUG("rlm_sql (%s): - sql_groupcmp finished: User is NOT a member of group %s",
-             inst->config->xlat_name, (char *)check->vp_strvalue);
+       RDEBUG("sql_groupcmp finished: User is NOT a member of group %s",
+              check->vp_strvalue);
 
        return 1;
 }
@@ -612,9 +678,8 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql
        /*
         *      Get the list of groups this user is a member of
         */
-       if (sql_get_grouplist(inst, sqlsocket, request, &group_list)) {
-               radlog(L_ERR, "rlm_sql (%s): Error retrieving group list",
-                      inst->config->xlat_name);
+       if (sql_get_grouplist(inst, sqlsocket, request, &group_list) < 0) {
+               radlog_request(L_ERR, 0, request, "Error retrieving group list");
                return -1;
        }
 
@@ -625,24 +690,24 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql
                 */
                sql_group = pairmake("Sql-Group", group_list_tmp->groupname, T_OP_EQ);
                if (!sql_group) {
-                       radlog(L_ERR, "rlm_sql (%s): Error creating Sql-Group attribute",
-                              inst->config->xlat_name);
+                       radlog_request(L_ERR, 0, request,
+                                      "Error creating Sql-Group attribute");
                        return -1;
                }
                pairadd(&request->packet->vps, sql_group);
                if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_check_query, request, sql_escape_func)) {
-                       radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user",
-                              inst->config->xlat_name);
+                       radlog_request(L_ERR, 0, request,
+                                      "Error generating query; rejecting user");
                        /* Remove the grouup we added above */
-                       pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                       pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
                        return -1;
                }
                rows = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr);
                if (rows < 0) {
-                       radlog(L_ERR, "rlm_sql (%s): Error retrieving check pairs for group %s",
-                              inst->config->xlat_name, group_list_tmp->groupname);
+                       radlog_request(L_ERR, 0, request, "Error retrieving check pairs for group %s",
+                              group_list_tmp->groupname);
                        /* Remove the grouup we added above */
-                       pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                       pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
                        pairfree(&check_tmp);
                        return -1;
                } else if (rows > 0) {
@@ -651,24 +716,23 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql
                         */
                        if (paircompare(request, request->packet->vps, check_tmp, &request->reply->vps) == 0) {
                                found = 1;
-                               DEBUG2("rlm_sql (%s): User found in group %s",
-                                       inst->config->xlat_name, group_list_tmp->groupname);
+                               RDEBUG2("User found in group %s",
+                                       group_list_tmp->groupname);
                                /*
                                 *      Now get the reply pairs since the paircompare matched
                                 */
                                if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func)) {
-                                       radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user",
-                                              inst->config->xlat_name);
+                                       radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
                                        /* Remove the grouup we added above */
-                                       pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                                       pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
                                        pairfree(&check_tmp);
                                        return -1;
                                }
                                if (sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr) < 0) {
-                                       radlog(L_ERR, "rlm_sql (%s): Error retrieving reply pairs for group %s",
-                                              inst->config->xlat_name, group_list_tmp->groupname);
+                                       radlog_request(L_ERR, 0, request, "Error retrieving reply pairs for group %s",
+                                              group_list_tmp->groupname);
                                        /* Remove the grouup we added above */
-                                       pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                                       pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
                                        pairfree(&check_tmp);
                                        pairfree(&reply_tmp);
                                        return -1;
@@ -685,24 +749,23 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql
                         *      match expected behavior
                         */
                        found = 1;
-                       DEBUG2("rlm_sql (%s): User found in group %s",
-                               inst->config->xlat_name, group_list_tmp->groupname);
+                       RDEBUG2("User found in group %s",
+                               group_list_tmp->groupname);
                        /*
                         *      Now get the reply pairs since the paircompare matched
                         */
                        if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func)) {
-                               radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user",
-                                      inst->config->xlat_name);
+                               radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
                                /* Remove the grouup we added above */
-                               pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                               pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
                                pairfree(&check_tmp);
                                return -1;
                        }
                        if (sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr) < 0) {
-                               radlog(L_ERR, "rlm_sql (%s): Error retrieving reply pairs for group %s",
-                                      inst->config->xlat_name, group_list_tmp->groupname);
+                               radlog_request(L_ERR, 0, request, "Error retrieving reply pairs for group %s",
+                                      group_list_tmp->groupname);
                                /* Remove the grouup we added above */
-                               pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                               pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
                                pairfree(&check_tmp);
                                pairfree(&reply_tmp);
                                return -1;
@@ -716,7 +779,7 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql
                 * Delete the Sql-Group we added above
                 * And clear out the pairlists
                 */
-               pairdelete(&request->packet->vps, PW_SQL_GROUP);
+               pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
                pairfree(&check_tmp);
                pairfree(&reply_tmp);
        }
@@ -730,20 +793,20 @@ static int rlm_sql_detach(void *instance)
 {
        SQL_INST *inst = instance;
 
-       if (inst->sqlpool) {
-               sql_poolfree(inst);
-       }
-
-       if (inst->config->xlat_name) {
-               xlat_unregister(inst->config->xlat_name,(RAD_XLAT_FUNC)sql_xlat);
-               free(inst->config->xlat_name);
-       }
-
        paircompare_unregister(PW_SQL_GROUP, sql_groupcmp);
 
        if (inst->config) {
                int i;
 
+               if (inst->sqlpool) {
+                       sql_poolfree(inst);
+               }
+
+               if (inst->config->xlat_name) {
+                       xlat_unregister(inst->config->xlat_name,(RAD_XLAT_FUNC)sql_xlat);
+                       free(inst->config->xlat_name);
+               }
+
                /*
                 *      Free up dynamically allocated string pointers.
                 */
@@ -766,7 +829,12 @@ static int rlm_sql_detach(void *instance)
                        free(*p);
                        *p = NULL;
                }
-               allowed_chars = NULL;
+               /*
+                *      Catch multiple instances of the module.
+                */
+               if (allowed_chars == inst->config->allowed_chars) {
+                       allowed_chars = NULL;
+               }
                free(inst->config);
                inst->config = NULL;
        }
@@ -795,6 +863,17 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
        memset(inst->config, 0, sizeof(SQL_CONFIG));
 
        /*
+        *      Export these methods, too.  This avoids RTDL_GLOBAL.
+        */
+       inst->sql_set_user = sql_set_user;
+       inst->sql_get_socket = sql_get_socket;
+       inst->sql_release_socket = sql_release_socket;
+       inst->sql_escape_func = sql_escape_func;
+       inst->sql_query = rlm_sql_query;
+       inst->sql_select_query = rlm_sql_select_query;
+       inst->sql_fetch_row = rlm_sql_fetch_row;
+
+       /*
         * If the configuration parameters can't be parsed, then
         * fail.
         */
@@ -804,15 +883,45 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
        }
 
        xlat_name = cf_section_name2(conf);
-       if (xlat_name == NULL)
+       if (xlat_name == NULL) {
                xlat_name = cf_section_name1(conf);
+       } else {
+               char *group_name;
+               DICT_ATTR *dattr;
+               ATTR_FLAGS flags;
+
+               /*
+                * Allocate room for <instance>-SQL-Group
+                */
+               group_name = rad_malloc((strlen(xlat_name) + 1 + 11) * sizeof(char));
+               sprintf(group_name,"%s-SQL-Group",xlat_name);
+               DEBUG("rlm_sql Creating new attribute %s",group_name);
+
+               memset(&flags, 0, sizeof(flags));
+               dict_addattr(group_name, 0, PW_TYPE_STRING, -1, flags);
+               dattr = dict_attrbyname(group_name);
+               if (dattr == NULL){
+                       radlog(L_ERR, "rlm_ldap: Failed to create attribute %s",group_name);
+                       free(group_name);
+                       free(inst);     /* FIXME: detach */
+                       return -1;
+               }
+
+               if (inst->config->groupmemb_query && 
+                   inst->config->groupmemb_query[0]) {
+                       DEBUG("rlm_sql: Registering sql_groupcmp for %s",group_name);
+                       paircompare_register(dattr->attr, PW_USER_NAME, sql_groupcmp, inst);
+               }
+
+               free(group_name);
+       }
        if (xlat_name){
                inst->config->xlat_name = strdup(xlat_name);
                xlat_register(xlat_name, (RAD_XLAT_FUNC)sql_xlat, inst);
        }
 
        if (inst->config->num_sql_socks > MAX_SQL_SOCKS) {
-               radlog(L_ERR | L_CONS, "rlm_sql (%s): sql_instantiate: number of sqlsockets cannot exceed MAX_SQL_SOCKS, %d",
+               radlog(L_ERR, "rlm_sql (%s): sql_instantiate: number of sqlsockets cannot exceed MAX_SQL_SOCKS, %d",
                       inst->config->xlat_name, MAX_SQL_SOCKS);
                rlm_sql_detach(inst);
                return -1;
@@ -822,27 +931,26 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
         *      Sanity check for crazy people.
         */
        if (strncmp(inst->config->sql_driver, "rlm_sql_", 8) != 0) {
-               radlog(L_ERR, "rlm_sql (%s): \"%s\" is NOT an SQL driver!",
-                      inst->config->xlat_name, inst->config->sql_driver);
+               radlog(L_ERR, "\"%s\" is NOT an SQL driver!",
+                      inst->config->sql_driver);
                rlm_sql_detach(inst);
                return -1;
        }
 
        inst->handle = lt_dlopenext(inst->config->sql_driver);
        if (inst->handle == NULL) {
-               radlog(L_ERR, "rlm_sql (%s): Could not link driver %s: %s",
-                      inst->config->xlat_name, inst->config->sql_driver,
+               radlog(L_ERR, "Could not link driver %s: %s",
+                      inst->config->sql_driver,
                       lt_dlerror());
-               radlog(L_ERR, "rlm_sql (%s): Make sure it (and all its dependent libraries!) are in the search path of your system's ld.",
-                      inst->config->xlat_name);
+               radlog(L_ERR, "Make sure it (and all its dependent libraries!) are in the search path of your system's ld.");
                rlm_sql_detach(inst);
                return -1;
        }
 
        inst->module = (rlm_sql_module_t *) lt_dlsym(inst->handle, inst->config->sql_driver);
        if (!inst->module) {
-               radlog(L_ERR, "rlm_sql (%s): Could not link symbol %s: %s",
-                      inst->config->xlat_name, inst->config->sql_driver,
+               radlog(L_ERR, "Could not link symbol %s: %s",
+                      inst->config->sql_driver,
                       lt_dlerror());
                rlm_sql_detach(inst);
                return -1;
@@ -860,11 +968,15 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
                rlm_sql_detach(inst);
                return -1;
        }
-       paircompare_register(PW_SQL_GROUP, PW_USER_NAME, sql_groupcmp, inst);
+
+       if (inst->config->groupmemb_query && 
+           inst->config->groupmemb_query[0]) {
+               paircompare_register(PW_SQL_GROUP, PW_USER_NAME, sql_groupcmp, inst);
+       }
 
        if (inst->config->do_clients){
                if (generate_sql_clients(inst) == -1){
-                       radlog(L_ERR, "rlm_sql (%s): generate_sql_clients() returned error",inst->config->xlat_name);
+                       radlog(L_ERR, "Failed to load clients from SQL.");
                        rlm_sql_detach(inst);
                        return -1;
                }
@@ -909,7 +1021,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
        sqlsocket = sql_get_socket(inst);
        if (sqlsocket == NULL) {
                /* Remove the username we (maybe) added above */
-               pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                return RLM_MODULE_FAIL;
        }
 
@@ -922,20 +1034,18 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
         * Alright, start by getting the specific entry for the user
         */
        if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_check_query, request, sql_escape_func)) {
-               radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user",
-                      inst->config->xlat_name);
+               radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
                sql_release_socket(inst, sqlsocket);
                /* Remove the username we (maybe) added above */
-               pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                return RLM_MODULE_FAIL;
        }
        rows = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr);
        if (rows < 0) {
-               radlog(L_ERR, "rlm_sql (%s): SQL query error; rejecting user",
-                      inst->config->xlat_name);
+               radlog_request(L_ERR, 0, request, "SQL query error; rejecting user");
                sql_release_socket(inst, sqlsocket);
                /* Remove the username we (maybe) added above */
-               pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                pairfree(&check_tmp);
                return RLM_MODULE_FAIL;
        } else if (rows > 0) {
@@ -944,32 +1054,36 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                 */
                if (paircompare(request, request->packet->vps, check_tmp, &request->reply->vps) == 0) {
                        found = 1;
-                       DEBUG2("rlm_sql (%s): User found in radcheck table", inst->config->xlat_name);
+                       RDEBUG2("User found in radcheck table");
+
+                       if (inst->config->authorize_reply_query &&
+                           *inst->config->authorize_reply_query) {
+
                        /*
                         *      Now get the reply pairs since the paircompare matched
                         */
                        if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_reply_query, request, sql_escape_func)) {
-                               radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user",
-                                      inst->config->xlat_name);
+                               radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
                                sql_release_socket(inst, sqlsocket);
                                /* Remove the username we (maybe) added above */
-                               pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+                               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                                pairfree(&check_tmp);
                                return RLM_MODULE_FAIL;
                        }
                        if (sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr) < 0) {
-                               radlog(L_ERR, "rlm_sql (%s): SQL query error; rejecting user",
-                                      inst->config->xlat_name);
+                               radlog_request(L_ERR, 0, request, "SQL query error; rejecting user");
                                sql_release_socket(inst, sqlsocket);
                                /* Remove the username we (maybe) added above */
-                               pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+                               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                                pairfree(&check_tmp);
                                pairfree(&reply_tmp);
                                return RLM_MODULE_FAIL;
                        }
+
                        if (!inst->config->read_groups)
                                dofallthrough = fallthrough(reply_tmp);
                        pairxlatmove(request, &request->reply->vps, &reply_tmp);
+                       }
                        pairxlatmove(request, &request->config_items, &check_tmp);
                }
        }
@@ -989,11 +1103,10 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
        if (dofallthrough) {
                rows = rlm_sql_process_groups(inst, request, sqlsocket, &dofallthrough);
                if (rows < 0) {
-                       radlog(L_ERR, "rlm_sql (%s): Error processing groups; rejecting user",
-                              inst->config->xlat_name);
+                       radlog_request(L_ERR, 0, request, "Error processing groups; rejecting user");
                        sql_release_socket(inst, sqlsocket);
                        /* Remove the username we (maybe) added above */
-                       pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+                       pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                        return RLM_MODULE_FAIL;
                } else if (rows > 0) {
                        found = 1;
@@ -1008,21 +1121,19 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                /*
                * Check for a default_profile or for a User-Profile.
                */
-               user_profile = pairfind(request->config_items, PW_USER_PROFILE);
+               user_profile = pairfind(request->config_items, PW_USER_PROFILE, 0);
                if (inst->config->default_profile[0] != 0 || user_profile != NULL){
                        char *profile = inst->config->default_profile;
 
                        if (user_profile != NULL)
                                profile = user_profile->vp_strvalue;
                        if (profile && strlen(profile)){
-                               radlog(L_DBG, "rlm_sql (%s): Checking profile %s",
-                                      inst->config->xlat_name, profile);
+                               RDEBUG("Checking profile %s", profile);
                                if (sql_set_user(inst, request, profileusername, profile) < 0) {
-                                       radlog(L_ERR, "rlm_sql (%s): Error setting profile; rejecting user",
-                                              inst->config->xlat_name);
+                                       radlog_request(L_ERR, 0, request, "Error setting profile; rejecting user");
                                        sql_release_socket(inst, sqlsocket);
                                        /* Remove the username we (maybe) added above */
-                                       pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+                                       pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                                        return RLM_MODULE_FAIL;
                                } else {
                                        profile_found = 1;
@@ -1033,11 +1144,10 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                if (profile_found) {
                        rows = rlm_sql_process_groups(inst, request, sqlsocket, &dofallthrough);
                        if (rows < 0) {
-                               radlog(L_ERR, "rlm_sql (%s): Error processing profile groups; rejecting user",
-                                      inst->config->xlat_name);
+                               radlog_request(L_ERR, 0, request, "Error processing profile groups; rejecting user");
                                sql_release_socket(inst, sqlsocket);
                                /* Remove the username we (maybe) added above */
-                               pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+                               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                                return RLM_MODULE_FAIL;
                        } else if (rows > 0) {
                                found = 1;
@@ -1046,12 +1156,11 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
        }
 
        /* Remove the username we (maybe) added above */
-       pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+       pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
        sql_release_socket(inst, sqlsocket);
 
        if (!found) {
-               radlog(L_DBG, "rlm_sql (%s): User %s not found",
-                      inst->config->xlat_name, sqlusername);
+               RDEBUG("User %s not found", sqlusername);
                return RLM_MODULE_NOTFOUND;
        } else {
                return RLM_MODULE_OK;
@@ -1082,12 +1191,11 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
        /*
         * Find the Acct Status Type
         */
-       if ((pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) != NULL) {
-               acctstatustype = pair->lvalue;
+       if ((pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE, 0)) != NULL) {
+               acctstatustype = pair->vp_integer;
        } else {
                radius_xlat(logstr, sizeof(logstr), "packet has no accounting status type. [user '%{User-Name}', nas '%{NAS-IP-Address}']", request, NULL);
-               radlog(L_ERR, "rlm_sql (%s) in sql_accounting: %s",
-                      inst->config->xlat_name, logstr);
+               radlog_request(L_ERR, 0, request, "%s", logstr);
                return RLM_MODULE_INVALID;
        }
 
@@ -1098,7 +1206,7 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
                         */
                case PW_STATUS_ACCOUNTING_ON:
                case PW_STATUS_ACCOUNTING_OFF:
-                       radlog(L_INFO, "rlm_sql (%s): received Acct On/Off packet", inst->config->xlat_name);
+                       RDEBUG("Received Acct On/Off packet");
                        radius_xlat(querystr, sizeof(querystr), inst->config->accounting_onoff_query, request, sql_escape_func);
                        query_log(request, inst, querystr);
 
@@ -1107,9 +1215,8 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
                                return(RLM_MODULE_FAIL);
                        if (*querystr) { /* non-empty query */
                                if (rlm_sql_query(sqlsocket, inst, querystr)) {
-                                       radlog(L_ERR, "rlm_sql (%s): Couldn't update SQL accounting for Acct On/Off packet - %s",
-                                              inst->config->xlat_name,
-                                              (char *)(inst->module->sql_error)(sqlsocket, inst->config));
+                                       radlog_request(L_ERR, 0, request, "Couldn't update SQL accounting for Acct On/Off packet - %s",
+                                              (inst->module->sql_error)(sqlsocket, inst->config));
                                        ret = RLM_MODULE_FAIL;
                                }
                                (inst->module->sql_finish_query)(sqlsocket, inst->config);
@@ -1135,9 +1242,8 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
                                return(RLM_MODULE_FAIL);
                        if (*querystr) { /* non-empty query */
                                if (rlm_sql_query(sqlsocket, inst, querystr)) {
-                                       radlog(L_ERR, "rlm_sql (%s): Couldn't update SQL accounting ALIVE record - %s",
-                                              inst->config->xlat_name,
-                                              (char *)(inst->module->sql_error)(sqlsocket, inst->config));
+                                       radlog_request(L_ERR, 0, request, "Couldn't update SQL accounting ALIVE record - %s",
+                                              (inst->module->sql_error)(sqlsocket, inst->config));
                                        ret = RLM_MODULE_FAIL;
                                }
                                else {
@@ -1154,9 +1260,8 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
                                                query_log(request, inst, querystr);
                                                if (*querystr) { /* non-empty query */
                                                        if (rlm_sql_query(sqlsocket, inst, querystr)) {
-                                                               radlog(L_ERR, "rlm_sql (%s): Couldn't insert SQL accounting ALIVE record - %s",
-                                                                          inst->config->xlat_name,
-                                                                          (char *)(inst->module->sql_error)(sqlsocket, inst->config));
+                                                               radlog_request(L_ERR, 0, request, "Couldn't insert SQL accounting ALIVE record - %s",
+                                                                      (inst->module->sql_error)(sqlsocket, inst->config));
                                                                ret = RLM_MODULE_FAIL;
                                                        }
                                                        (inst->module->sql_finish_query)(sqlsocket, inst->config);
@@ -1185,9 +1290,8 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
                                return(RLM_MODULE_FAIL);
                        if (*querystr) { /* non-empty query */
                                if (rlm_sql_query(sqlsocket, inst, querystr)) {
-                                       radlog(L_ERR, "rlm_sql (%s): Couldn't insert SQL accounting START record - %s",
-                                              inst->config->xlat_name,
-                                              (char *)(inst->module->sql_error)(sqlsocket, inst->config));
+                                       radlog_request(L_ERR, 0, request, "Couldn't insert SQL accounting START record - %s",
+                                              (inst->module->sql_error)(sqlsocket, inst->config));
 
                                        /*
                                         * We failed the insert above.  It's probably because
@@ -1199,9 +1303,8 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
 
                                        if (*querystr) { /* non-empty query */
                                                if (rlm_sql_query(sqlsocket, inst, querystr)) {
-                                                       radlog(L_ERR, "rlm_sql (%s): Couldn't update SQL accounting START record - %s",
-                                                              inst->config->xlat_name,
-                                                              (char *)(inst->module->sql_error)(sqlsocket, inst->config));
+                                                       radlog_request(L_ERR, 0, request, "Couldn't update SQL accounting START record - %s",
+                                                              (inst->module->sql_error)(sqlsocket, inst->config));
                                                        ret = RLM_MODULE_FAIL;
                                                }
                                                (inst->module->sql_finish_query)(sqlsocket, inst->config);
@@ -1229,9 +1332,8 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
                                return(RLM_MODULE_FAIL);
                        if (*querystr) { /* non-empty query */
                                if (rlm_sql_query(sqlsocket, inst, querystr)) {
-                                       radlog(L_ERR, "rlm_sql (%s): Couldn't update SQL accounting STOP record - %s",
-                                              inst->config->xlat_name,
-                                              (char *)(inst->module->sql_error)(sqlsocket, inst->config));
+                                       radlog_request(L_ERR, 0, request, "Couldn't update SQL accounting STOP record - %s",
+                                              (inst->module->sql_error)(sqlsocket, inst->config));
                                        ret = RLM_MODULE_FAIL;
                                }
                                else {
@@ -1250,14 +1352,14 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
                                                 * This is to fix CISCO's aaa from filling our
                                                 * table with bogus crap
                                                 */
-                                               if ((pair = pairfind(request->packet->vps, PW_ACCT_SESSION_TIME)) != NULL)
-                                                       acctsessiontime = pair->lvalue;
+                                               if ((pair = pairfind(request->packet->vps, PW_ACCT_SESSION_TIME, 0)) != NULL)
+                                                       acctsessiontime = pair->vp_integer;
 
                                                if (acctsessiontime <= 0) {
                                                        radius_xlat(logstr, sizeof(logstr), "stop packet with zero session length. [user '%{User-Name}', nas '%{NAS-IP-Address}']", request, NULL);
-                                                       radlog(L_ERR, "rlm_sql (%s) in sql_accounting: %s", inst->config->xlat_name, logstr);
+                                                       radlog_request(L_DBG, 0, request, "%s", logstr);
                                                        sql_release_socket(inst, sqlsocket);
-                                                       ret = RLM_MODULE_NOOP;
+                                                       return RLM_MODULE_NOOP;
                                                }
 #endif
 
@@ -1266,9 +1368,9 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
 
                                                if (*querystr) { /* non-empty query */
                                                        if (rlm_sql_query(sqlsocket, inst, querystr)) {
-                                                               radlog(L_ERR, "rlm_sql (%s): Couldn't insert SQL accounting STOP record - %s",
-                                                                               inst->config->xlat_name,
-                                                                               (char *)(inst->module->sql_error)(sqlsocket, inst->config));
+                                                               radlog_request(L_ERR, 0, request, "Couldn't insert SQL accounting STOP record - %s",
+
+                                                                      (inst->module->sql_error)(sqlsocket, inst->config));
                                                                ret = RLM_MODULE_FAIL;
                                                        }
                                                        (inst->module->sql_finish_query)(sqlsocket, inst->config);
@@ -1283,7 +1385,8 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
                         *      Anything else is ignored.
                         */
                default:
-                       radlog(L_INFO, "rlm_sql (%s): Unsupported Acct-Status-Type = %d", inst->config->xlat_name, acctstatustype);
+                       RDEBUG("Unsupported Acct-Status-Type = %d",
+                      acctstatustype);
                        return RLM_MODULE_NOOP;
                        break;
 
@@ -1319,12 +1422,13 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) {
        int             nas_port = 0;
 
        /* If simul_count_query is not defined, we don't do any checking */
-       if (inst->config->simul_count_query[0] == 0) {
+       if (!inst->config->simul_count_query ||
+           (inst->config->simul_count_query[0] == 0)) {
                return RLM_MODULE_NOOP;
        }
 
        if((request->username == NULL) || (request->username->length == 0)) {
-               radlog(L_ERR, "rlm_sql (%s): Zero Length username not permitted\n", inst->config->xlat_name);
+               radlog_request(L_ERR, 0, request, "Zero Length username not permitted\n");
                return RLM_MODULE_INVALID;
        }
 
@@ -1372,14 +1476,15 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) {
         *      Looks like too many sessions, so let's start verifying
         *      them, unless told to rely on count query only.
         */
-       if (inst->config->simul_verify_query[0] == '\0') {
+       if (!inst->config->simul_verify_query ||
+           (inst->config->simul_verify_query[0] == '\0')) {
                sql_release_socket(inst, sqlsocket);
                return RLM_MODULE_OK;
        }
 
        radius_xlat(querystr, sizeof(querystr), inst->config->simul_verify_query, request, sql_escape_func);
        if(rlm_sql_select_query(sqlsocket, inst, querystr)) {
-               radlog(L_ERR, "rlm_sql (%s): sql_checksimul: Database query error", inst->config->xlat_name);
+               radlog_request(L_ERR, 0, request, "Database query error");
                sql_release_socket(inst, sqlsocket);
                return RLM_MODULE_FAIL;
        }
@@ -1389,9 +1494,9 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) {
          */
        request->simul_count = 0;
 
-        if ((vp = pairfind(request->packet->vps, PW_FRAMED_IP_ADDRESS)) != NULL)
-                ipno = vp->lvalue;
-        if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) != NULL)
+        if ((vp = pairfind(request->packet->vps, PW_FRAMED_IP_ADDRESS, 0)) != NULL)
+                ipno = vp->vp_ipaddr;
+        if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID, 0)) != NULL)
                 call_num = vp->vp_strvalue;
 
 
@@ -1402,13 +1507,13 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) {
                if (!row[2]){
                        (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
                        sql_release_socket(inst, sqlsocket);
-                       DEBUG("rlm_sql (%s): Cannot zap stale entry. No username present in entry.", inst->config->xlat_name);
+                       RDEBUG("Cannot zap stale entry. No username present in entry.", inst->config->xlat_name);
                        return RLM_MODULE_FAIL;
                }
                if (!row[1]){
                        (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
                        sql_release_socket(inst, sqlsocket);
-                       DEBUG("rlm_sql (%s): Cannot zap stale entry. No session id in entry.", inst->config->xlat_name);
+                       RDEBUG("Cannot zap stale entry. No session id in entry.", inst->config->xlat_name);
                        return RLM_MODULE_FAIL;
                }
                if (row[3])
@@ -1464,7 +1569,7 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) {
                         */
                        (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
                        sql_release_socket(inst, sqlsocket);
-                       radlog(L_ERR, "rlm_sql (%s): sql_checksimul: Failed to check the terminal server for user '%s'.", inst->config->xlat_name, row[2]);
+                       radlog_request(L_ERR, 0, request, "Failed to check the terminal server for user '%s'.", row[2]);
                        return RLM_MODULE_FAIL;
                }
        }
@@ -1489,13 +1594,12 @@ static int rlm_sql_postauth(void *instance, REQUEST *request) {
        char            querystr[MAX_QUERY_LEN];
        char            sqlusername[MAX_STRING_LEN];
 
-       DEBUG("rlm_sql (%s): Processing sql_postauth", inst->config->xlat_name);
-
        if(sql_set_user(inst, request, sqlusername, NULL) < 0)
                return RLM_MODULE_FAIL;
 
        /* If postauth_query is not defined, we stop here */
-       if (inst->config->postauth_query[0] == '\0')
+       if (!inst->config->postauth_query ||
+           (inst->config->postauth_query[0] == '\0'))
                return RLM_MODULE_NOOP;
 
        /* Expand variables in the query */
@@ -1515,7 +1619,7 @@ static int rlm_sql_postauth(void *instance, REQUEST *request) {
        if (rlm_sql_query(sqlsocket, inst, querystr)) {
                radlog(L_ERR, "rlm_sql (%s) in sql_postauth: Database query error - %s",
                       inst->config->xlat_name,
-                      (char *)(inst->module->sql_error)(sqlsocket, inst->config));
+                      (inst->module->sql_error)(sqlsocket, inst->config));
                sql_release_socket(inst, sqlsocket);
                return RLM_MODULE_FAIL;
        }