Ejemplo n.º 1
0
/** Call the driver's sql_query method, reconnecting if necessary.
 *
 * @param handle to query the database with. *handle should not be NULL, as this indicates
 *	  previous reconnection attempt has failed.
 * @param inst rlm_sql instance data.
 * @param query to execute. Should not be zero length.
 * @return RLM_SQL_OK on success, RLM_SQL_RECONNECT if a new handle is required (also sets *handle = NULL),
 *         RLM_SQL_QUERY_ERROR/RLM_SQL_ERROR on invalid query or connection error, RLM_SQL_DUPLICATE on constraints
 *         violation.
 */
sql_rcode_t rlm_sql_query(rlm_sql_handle_t **handle, rlm_sql_t *inst, char const *query)
{
	int ret = RLM_SQL_ERROR;
	int i, count;

	/* There's no query to run, return an error */
	if (query[0] == '\0') {
		ERROR("rlm_sql (%s): Zero length query", inst->config->xlat_name);
		return RLM_SQL_QUERY_ERROR;
	}

	/* There's no handle, we need a new one */
	if (!*handle) return RLM_SQL_RECONNECT;

	/*
	 *  inst->pool may be NULL is this function is called by mod_conn_create.
	 */
	count = inst->pool ? fr_connection_get_num(inst->pool) : 0;

	/*
	 *  Here we try with each of the existing connections, then try to create
	 *  a new connection, then give up.
	 */
	for (i = 0; i < (count + 1); i++) {
		DEBUG("rlm_sql (%s): Executing query: '%s'", inst->config->xlat_name, query);

		ret = (inst->module->sql_query)(*handle, inst->config, query);
		switch (ret) {
		case RLM_SQL_OK:
			break;

		/*
		 *	Run through all available sockets until we exhaust all existing
		 *	sockets in the pool and fail to establish a *new* connection.
		 */
		case RLM_SQL_RECONNECT:
			*handle = fr_connection_reconnect(inst->pool, *handle);
			/* Reconnection failed */
			if (!*handle) return RLM_SQL_RECONNECT;
			/* Reconnection succeeded, try again with the new handle */
			continue;

		case RLM_SQL_QUERY_ERROR:
		case RLM_SQL_ERROR:
			rlm_sql_query_error(*handle, inst);
			break;

		case RLM_SQL_DUPLICATE:
			rlm_sql_query_debug(*handle, inst);
			break;

		}

		return ret;
	}

	ERROR("rlm_sql (%s): Hit reconnection limit", inst->config->xlat_name);

	return RLM_SQL_ERROR;
}
Ejemplo n.º 2
0
/*************************************************************************
 *
 *	Function: rlm_sql_select_query
 *
 *	Purpose: call the module's sql_select_query and implement re-connect
 *
 *************************************************************************/
int rlm_sql_select_query(SQLSOCK *sqlsocket, SQL_INST *inst, char *query)
{
	int ret;

	/*
	 *	If there's no query, return an error.
	 */
	if (!query || !*query) {
		return -1;
	}

	if (sqlsocket->conn) {
		ret = (inst->module->sql_select_query)(sqlsocket, inst->config,
						       query);
	} else {
		ret = SQL_DOWN;
	}

	if (ret == SQL_DOWN) {
		sqlsocket = fr_connection_reconnect(inst->pool, sqlsocket);
		if (!sqlsocket) return -1;

		/* retry the query on the newly connected socket */
		ret = (inst->module->sql_select_query)(sqlsocket, inst->config, query);

		if (ret) {
			radlog(L_ERR, "rlm_sql (%s): failed after re-connect",
			       inst->config->xlat_name);
			return -1;
		}
	}

	return ret;
}
Ejemplo n.º 3
0
/*************************************************************************
 *
 *	Function: rlm_sql_fetch_row
 *
 *	Purpose: call the module's sql_fetch_row and implement re-connect
 *
 *************************************************************************/
int rlm_sql_fetch_row(SQLSOCK *sqlsocket, SQL_INST *inst)
{
	int ret;

	if (sqlsocket->conn) {
		ret = (inst->module->sql_fetch_row)(sqlsocket, inst->config);
	} else {
		ret = SQL_DOWN;
	}

	if (ret == SQL_DOWN) {
		sqlsocket = fr_connection_reconnect(inst->pool, sqlsocket);
		if (!sqlsocket) return -1;

		/* retry the query on the newly connected socket */
		ret = (inst->module->sql_fetch_row)(sqlsocket, inst->config);

		if (ret) {
			radlog(L_ERR, "rlm_sql (%s): failed after re-connect",
			       inst->config->xlat_name);
			return -1;
		}
	}

	return ret;
}
Ejemplo n.º 4
0
/** Call the driver's sql_select_query method, reconnecting if necessary.
 *
 * @note Caller must call ``(inst->module->sql_finish_select_query)(handle, inst->config);``
 *	after they're done with the result.
 *
 * @param inst #rlm_sql_t instance data.
 * @param request Current request.
 * @param handle to query the database with. *handle should not be NULL, as this indicates
 *	  previous reconnection attempt has failed.
 * @param query to execute. Should not be zero length.
 * @return
 *	- #RLM_SQL_OK on success.
 *	- #RLM_SQL_RECONNECT if a new handle is required (also sets *handle = NULL).
 *	- #RLM_SQL_QUERY_INVALID, #RLM_SQL_ERROR on invalid query or connection error.
 */
sql_rcode_t rlm_sql_select_query(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t **handle,  char const *query)
{
	int ret = RLM_SQL_ERROR;
	int i, count;

	/* Caller should check they have a valid handle */
	rad_assert(*handle);

	/* There's no query to run, return an error */
	if (query[0] == '\0') {
		if (request) REDEBUG("Zero length query");

		return RLM_SQL_QUERY_INVALID;
	}

	/*
	 *  inst->pool may be NULL is this function is called by mod_conn_create.
	 */
	count = inst->pool ? fr_connection_get_num(inst->pool) : 0;

	/*
	 *  For sanity, for when no connections are viable, and we can't make a new one
	 */
	for (i = 0; i < (count + 1); i++) {
		ROPTIONAL(RDEBUG2, DEBUG2, "Executing select query: %s", query);

		ret = (inst->module->sql_select_query)(*handle, inst->config, query);
		switch (ret) {
		case RLM_SQL_OK:
			break;

		/*
		 *	Run through all available sockets until we exhaust all existing
		 *	sockets in the pool and fail to establish a *new* connection.
		 */
		case RLM_SQL_RECONNECT:
			*handle = fr_connection_reconnect(inst->pool, *handle);
			/* Reconnection failed */
			if (!*handle) return RLM_SQL_RECONNECT;
			/* Reconnection succeeded, try again with the new handle */
			continue;

		case RLM_SQL_QUERY_INVALID:
		case RLM_SQL_ERROR:
		default:
			rlm_sql_print_error(inst, request, *handle, false);
			(inst->module->sql_finish_select_query)(*handle, inst->config);
			break;
		}

		return ret;
	}

	ROPTIONAL(RERROR, ERROR, "Hit reconnection limit");

	return RLM_SQL_ERROR;
}
Ejemplo n.º 5
0
/*
 *	Query the redis database
 */
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 %s ...", argv[0]);
	dissocket->reply = redisCommandArgv(dissocket->conn, argc, argv, NULL);

	if (!dissocket->reply) {
		radlog(L_ERR, "rlm_redis: (%s) REDIS error: %s",
		       inst->xlat_name, dissocket->conn->errstr);

		dissocket = fr_connection_reconnect(inst->pool, dissocket);
		if (!dissocket) {
		error:
			*dissocket_p = NULL;
			return -1;
		}

		dissocket->reply = redisCommand(dissocket->conn, query);
		if (!dissocket->reply) {
			radlog(L_ERR, "rlm_redis (%s): failed after re-connect",
			       inst->xlat_name);
			fr_connection_del(inst->pool, dissocket);
			goto error;
		}

		*dissocket_p = dissocket;
	}

	if (dissocket->reply->type == REDIS_REPLY_ERROR) {
		radlog(L_ERR, "rlm_redis (%s): query failed, %s",
		       inst->xlat_name, query);
		return -1;
	}

	return 0;
}
Ejemplo n.º 6
0
/** Reconnect a socket
 *
 * @param inst main rlm_cache instance.
 * @param request The current request.
 * @param handle Pointer to the handle to reconnect (will be set to NULL if reconnection fails).
 */
static int mod_conn_reconnect(rlm_cache_t *inst, UNUSED REQUEST *request, rlm_cache_handle_t **handle)
{
	rlm_cache_memcached_t *driver = inst->driver;
	rlm_cache_handle_t *mandle;

	mandle = fr_connection_reconnect(driver->pool, *handle);
	if (!mandle) {
		*handle = NULL;
		return -1;
	}
	*handle = mandle;

	return 0;
}
Ejemplo n.º 7
0
/** Call the driver's sql_query method, reconnecting if necessary.
 *
 * @param handle to query the database with. *handle should not be NULL, as this indicates
 *	  previous reconnection attempt has failed.
 * @param inst rlm_sql instance data.
 * @param query to execute. Should not be zero length.
 * @return RLM_SQL_OK on success, RLM_SQL_RECONNECT if a new handle is required (also sets *handle = NULL),
 *         RLM_SQL_QUERY_ERROR/RLM_SQL_ERROR on invalid query or connection error, RLM_SQL_DUPLICATE on constraints
 *         violation.
 */
sql_rcode_t rlm_sql_query(rlm_sql_handle_t **handle, rlm_sql_t *inst, char const *query)
{
	int ret = RLM_SQL_ERROR;
	int i;

	/* There's no query to run, return an error */
	if (query[0] == '\0') return RLM_SQL_QUERY_ERROR;

	/* There's no handle, we need a new one */
	if (!*handle) return RLM_SQL_RECONNECT;

	/* For sanity, for when no connections are viable, and we can't make a new one */
	for (i = fr_connection_get_num(inst->pool); i >= 0; i--) {
		DEBUG("rlm_sql (%s): Executing query: '%s'", inst->config->xlat_name, query);

		ret = (inst->module->sql_query)(*handle, inst->config, query);
		switch (ret) {
		case RLM_SQL_OK:
			break;

		/*
		 *	Run through all available sockets until we exhaust all existing
		 *	sockets in the pool and fail to establish a *new* connection.
		 */
		case RLM_SQL_RECONNECT:
			*handle = fr_connection_reconnect(inst->pool, *handle);
			/* Reconnection failed */
			if (!*handle) return RLM_SQL_RECONNECT;
			/* Reconnection succeeded, try again with the new handle */
			continue;

		case RLM_SQL_QUERY_ERROR:
		case RLM_SQL_ERROR:
			rlm_sql_query_error(*handle, inst);
			break;

		case RLM_SQL_DUPLICATE:
			rlm_sql_query_debug(*handle, inst);
			break;

		}

		return ret;
	}

	ERROR("rlm_sql (%s): Hit reconnection limit", inst->config->xlat_name);

	return RLM_SQL_ERROR;
}
Ejemplo n.º 8
0
/*************************************************************************
 *
 *	Function: rlm_sql_query
 *
 *	Purpose: call the module's sql_query and implement re-connect
 *
 *************************************************************************/
int rlm_sql_query(rlm_sql_handle_t **handle, rlm_sql_t *inst, char const *query)
{
	int ret = -1;

	/*
	 *	If there's no query, return an error.
	 */
	if (!query || !*query) {
		return -1;
	}

	if (!*handle || !(*handle)->conn) {
		goto sql_down;
	}

	while (true) {
		DEBUG("rlm_sql (%s): Executing query: '%s'", inst->config->xlat_name, query);

		ret = (inst->module->sql_query)(*handle, inst->config, query);
		switch (ret) {
		case RLM_SQL_OK:
			break;

		/*
		 *	Run through all available sockets until we exhaust all existing
		 *	sockets in the pool and fail to establish a *new* connection.
		 */
		case RLM_SQL_RECONNECT:
		sql_down:
			*handle = fr_connection_reconnect(inst->pool, *handle);
			if (!*handle) return RLM_SQL_RECONNECT;
			continue;

		case RLM_SQL_QUERY_ERROR:
		case RLM_SQL_ERROR:
			rlm_sql_query_error(*handle, inst);
			break;

		case RLM_SQL_DUPLICATE:
			rlm_sql_query_debug(*handle, inst);
			break;

		}

		return ret;
	}
}
Ejemplo n.º 9
0
/*
 *	Query the redis database
 */
int rlm_redis_query(REDISSOCK **dissocket_p, REDIS_INST *inst, char *query)
{
    REDISSOCK *dissocket;

    if (!query || !*query || !inst || !dissocket_p) {
        return -1;
    }

    dissocket = *dissocket_p;

    DEBUG2("executing query %s", query);
    dissocket->reply = redisCommand(dissocket->conn, query);

    if (!dissocket->reply) {
        radlog(L_ERR, "rlm_redis: (%s) REDIS error: %s",
               inst->xlat_name, dissocket->conn->errstr);

        dissocket = fr_connection_reconnect(inst->pool, dissocket);
        if (!dissocket) {
error:
            *dissocket_p = NULL;
            return -1;
        }

        dissocket->reply = redisCommand(dissocket->conn, query);
        if (!dissocket->reply) {
            radlog(L_ERR, "rlm_redis (%s): failed after re-connect",
                   inst->xlat_name);
            fr_connection_del(inst->pool, dissocket);
            goto error;
        }

        *dissocket_p = dissocket;
    }

    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;
    }

    return 0;
}
Ejemplo n.º 10
0
/*************************************************************************
 *
 *	Function: rlm_sql_select_query
 *
 *	Purpose: call the module's sql_select_query and implement re-connect
 *
 *************************************************************************/
int rlm_sql_select_query(SQLSOCK **sqlsocket, SQL_INST *inst, char *query)
{
	int ret;

	/*
	 *	If there's no query, return an error.
	 */
	if (!query || !*query) {
		return -1;
	}

	if (!*sqlsocket || !(*sqlsocket)->conn) {
		ret = -1;
		goto sql_down;
	}
	
	while (1) {
		DEBUG("rlm_sql (%s): Executing query: '%s'",
		      inst->config->xlat_name, query);

		ret = (inst->module->sql_select_query)(*sqlsocket, inst->config, query);
		/*
		 * Run through all available sockets until we exhaust all existing
		 * sockets in the pool and fail to establish a *new* connection.
		 */
		if (ret == SQL_DOWN) {
			sql_down:
			*sqlsocket = fr_connection_reconnect(inst->pool, *sqlsocket);
			if (!*sqlsocket) return SQL_DOWN;
			
			continue;
		}
		
		if (ret < 0) {
			radlog(L_ERR,
				   "rlm_sql (%s): Database query error '%s'",
				   inst->config->xlat_name,
				   (inst->module->sql_error)(*sqlsocket, inst->config));
		}
		
		return ret;
	}
}
Ejemplo n.º 11
0
/*************************************************************************
 *
 *	Function: rlm_sql_select_query
 *
 *	Purpose: call the module's sql_select_query and implement re-connect
 *
 *************************************************************************/
int rlm_sql_select_query(rlm_sql_handle_t **handle, rlm_sql_t *inst, char const *query)
{
	int ret;

	/*
	 *	If there's no query, return an error.
	 */
	if (!query || !*query) {
		return -1;
	}

	if (!*handle || !(*handle)->conn) {
		ret = -1;
		goto sql_down;
	}

	while (1) {
		DEBUG("rlm_sql (%s): Executing query: '%s'",
		      inst->config->xlat_name, query);

		ret = (inst->module->sql_select_query)(*handle, inst->config, query);
		/*
		 * Run through all available sockets until we exhaust all existing
		 * sockets in the pool and fail to establish a *new* connection.
		 */
		if (ret == RLM_SQL_RECONNECT) {
			sql_down:
			*handle = fr_connection_reconnect(inst->pool, *handle);
			if (!*handle) return RLM_SQL_RECONNECT;

			continue;
		}

		if (ret < 0) {
			char const *error = (inst->module->sql_error)(*handle, inst->config);
			ERROR("rlm_sql (%s): Database query error '%s'",
			      inst->config->xlat_name, error ? error : "<UNKNOWN>");
		}

		return ret;
	}
}
Ejemplo n.º 12
0
/** Call the driver's sql_query method, reconnecting if necessary.
 *
 * @note Caller must call ``(inst->module->sql_finish_query)(handle, inst->config);``
 *	after they're done with the result.
 *
 * @param handle to query the database with. *handle should not be NULL, as this indicates
 * 	previous reconnection attempt has failed.
 * @param request Current request.
 * @param inst #rlm_sql_t instance data.
 * @param query to execute. Should not be zero length.
 * @return
 *	- #RLM_SQL_OK on success.
 *	- #RLM_SQL_RECONNECT if a new handle is required (also sets *handle = NULL).
 *	- #RLM_SQL_QUERY_INVALID, #RLM_SQL_ERROR on invalid query or connection error.
 *	- #RLM_SQL_ALT_QUERY on constraints violation.
 */
sql_rcode_t rlm_sql_query(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t **handle, char const *query)
{
	int ret = RLM_SQL_ERROR;
	int i, count;

	/* Caller should check they have a valid handle */
	rad_assert(*handle);

	/* There's no query to run, return an error */
	if (query[0] == '\0') {
		if (request) REDEBUG("Zero length query");
		return RLM_SQL_QUERY_INVALID;
	}

	/*
	 *  inst->pool may be NULL is this function is called by mod_conn_create.
	 */
	count = inst->pool ? fr_connection_get_num(inst->pool) : 0;

	/*
	 *  Here we try with each of the existing connections, then try to create
	 *  a new connection, then give up.
	 */
	for (i = 0; i < (count + 1); i++) {
		ROPTIONAL(RDEBUG2, DEBUG2, "Executing query: %s", query);

		ret = (inst->module->sql_query)(*handle, inst->config, query);
		switch (ret) {
		case RLM_SQL_OK:
			break;

		/*
		 *	Run through all available sockets until we exhaust all existing
		 *	sockets in the pool and fail to establish a *new* connection.
		 */
		case RLM_SQL_RECONNECT:
			*handle = fr_connection_reconnect(inst->pool, *handle);
			/* Reconnection failed */
			if (!*handle) return RLM_SQL_RECONNECT;
			/* Reconnection succeeded, try again with the new handle */
			continue;

		/*
		 *	These are bad and should make rlm_sql return invalid
		 */
		case RLM_SQL_QUERY_INVALID:
			rlm_sql_print_error(inst, request, *handle, false);
			(inst->module->sql_finish_query)(*handle, inst->config);
			break;

		/*
		 *	Server or client errors.
		 *
		 *	If the driver claims to be able to distinguish between
		 *	duplicate row errors and other errors, and we hit a
		 *	general error treat it as a failure.
		 *
		 *	Otherwise rewrite it to RLM_SQL_ALT_QUERY.
		 */
		case RLM_SQL_ERROR:
			if (inst->module->flags & RLM_SQL_RCODE_FLAGS_ALT_QUERY) {
				rlm_sql_print_error(inst, request, *handle, false);
				(inst->module->sql_finish_query)(*handle, inst->config);
				break;
			}
			ret = RLM_SQL_ALT_QUERY;
			/* FALL-THROUGH */

		/*
		 *	Driver suggested using an alternative query
		 */
		case RLM_SQL_ALT_QUERY:
			rlm_sql_print_error(inst, request, *handle, true);
			(inst->module->sql_finish_query)(*handle, inst->config);
			break;

		}

		return ret;
	}

	ROPTIONAL(RERROR, ERROR, "Hit reconnection limit");

	return RLM_SQL_ERROR;
}