23 RCSID(
"$Id: 0a2c57e48d029dd28b322a3c4d9cd8f09b337b10 $")
25 #define LOG_PREFIX "sql - oracle"
27 #include <freeradius-devel/server/base.h>
28 #include <freeradius-devel/util/debug.h>
42 #if defined(__STDC__) && __STDC__
102 #define MAX_DATASTR_LEN 64
123 OCIErrorGet((dvoid *) conn->
error, 1, (OraText *) NULL, &errcode, (OraText *)
out,
124 outlen, OCI_HTYPE_ERROR);
125 if (!errcode)
return -1;
150 if (ret < 0)
return 0;
153 out[0].msg = talloc_strdup(ctx, errbuff);
162 if (
inst->pool) OCISessionPoolDestroy((dvoid *)
inst->pool, (dvoid *)
inst->error, OCI_DEFAULT );
163 if (
inst->error) OCIHandleFree((dvoid *)
inst->error, OCI_HTYPE_ERROR);
164 if (
inst->env) OCIHandleFree((dvoid *)
inst->env, OCI_HTYPE_ENV);
176 OraText *sql_password = NULL;
177 OraText *sql_login = NULL;
180 ERROR(
"Couldn't load mctx->configuration of session pool(\"spool\" section in driver mctx->config)");
187 if (OCIEnvCreate(&
inst->env, OCI_DEFAULT | OCI_THREADED, NULL, NULL, NULL, NULL, 0, NULL)) {
188 ERROR(
"Couldn't init Oracle OCI environment (OCIEnvCreate())");
196 if (OCIHandleAlloc((dvoid *)
inst->env, (dvoid **)&
inst->error, OCI_HTYPE_ERROR, 0, NULL)) {
197 ERROR(
"Couldn't init Oracle ERROR handle (OCIHandleAlloc())");
205 if (OCIHandleAlloc((dvoid *)
inst->env, (dvoid **)&
inst->pool, OCI_HTYPE_SPOOL, 0, NULL)) {
206 ERROR(
"Couldn't init Oracle session pool (OCIHandleAlloc())");
213 DEBUG2(
"OCISessionPoolCreate min=%d max=%d inc=%d",
inst->spool_min,
inst->spool_max,
inst->spool_inc);
216 memcpy(&sql_login, &
config->sql_login,
sizeof(sql_login));
217 memcpy(&sql_password, &
config->sql_password,
sizeof(sql_password));
219 if (OCISessionPoolCreate((dvoid *)
inst->env, (dvoid *)
inst->error, (dvoid *)
inst->pool,
220 (OraText**)&
inst->pool_name, (ub4*)&
inst->pool_name_len,
221 (CONST OraText *)
config->sql_db, strlen(
config->sql_db),
223 sql_login, strlen(
config->sql_login),
224 sql_password, strlen(
config->sql_password),
225 OCI_SPC_STMTCACHE | OCI_SPC_HOMOGENEOUS)) {
228 OCIErrorGet((dvoid *)
inst->error, 1, (OraText *) NULL, &errcode, (OraText *) errbuff,
229 sizeof(errbuff), OCI_HTYPE_ERROR);
232 ERROR(
"Oracle create session pool failed: '%s'", errbuff);
236 if (
inst->spool_timeout > 0) {
237 if (OCIAttrSet(
inst->pool, OCI_HTYPE_SPOOL, &
inst->spool_timeout, 0,
238 OCI_ATTR_SPOOL_TIMEOUT,
inst->error) != OCI_SUCCESS) {
239 ERROR(
"Couldn't set Oracle session idle time");
244 if (OCIAttrSet(
inst->pool, OCI_HTYPE_SPOOL, &
inst->stmt_cache_size, 0,
245 OCI_ATTR_SPOOL_STMTCACHESIZE,
inst->error) != OCI_SUCCESS) {
246 ERROR(
"Couldn't set Oracle default statement cache size");
259 if (strstr(errbuff,
"ORA-03113") || strstr(errbuff,
"ORA-03114")) {
260 ERROR(
"OCI_SERVER_NOT_CONNECTED");
269 if (conn->
ctx) OCISessionRelease(conn->
ctx, conn->
error, NULL, 0, OCI_DEFAULT);
270 if (conn->
error) OCIHandleFree((dvoid *)conn->
error, OCI_HTYPE_ERROR);
288 if (OCIHandleAlloc((dvoid *)
inst->env, (dvoid **)&conn->
error, OCI_HTYPE_ERROR, 0, NULL)) {
289 ERROR(
"Couldn't init Oracle ERROR handle (OCIHandleAlloc())");
297 if (OCISessionGet((dvoid *)
inst->env, conn->
error, &conn->
ctx, NULL,
298 (OraText *)
inst->pool_name,
inst->pool_name_len,
299 NULL, 0, NULL, NULL, NULL,
300 OCI_SESSGET_SPOOL | OCI_SESSGET_STMTCACHE) != OCI_SUCCESS) {
301 ERROR(
"Oracle get sessin from pool[%s] failed: '%s'",
314 int fields, i, status;
318 if (OCIAttrGet((dvoid *)conn->
query, OCI_HTYPE_STMT, (dvoid *)&fields, NULL, OCI_ATTR_PARAM_COUNT,
322 MEM(
names = talloc_array(query_ctx,
char const *, fields));
324 for (i = 0; i < fields; i++) {
325 OraText *pcol_name = NULL;
328 status = OCIParamGet(conn->
query, OCI_HTYPE_STMT, conn->
error, (dvoid **)¶m, i + 1);
329 if (status != OCI_SUCCESS) {
330 ERROR(
"OCIParamGet(OCI_HTYPE_STMT) failed in sql_fields()");
337 status = OCIAttrGet((dvoid **)param, OCI_DTYPE_PARAM, &pcol_name, &pcol_size,
338 OCI_ATTR_NAME, conn->
error);
339 if (status != OCI_SUCCESS) {
340 ERROR(
"OCIParamGet(OCI_ATTR_NAME) failed in sql_fields()");
345 names[i] = (
char const *)pcol_name;
360 ERROR(
"Socket not connected");
369 NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT)) {
370 ERROR(
"prepare failed in sql_query");
375 status = OCIStmtExecute(conn->
ctx, conn->
query, conn->
error, 1, 0,
376 NULL, NULL, OCI_COMMIT_ON_SUCCESS);
378 if (status == OCI_SUCCESS) {
382 if (status == OCI_ERROR) {
383 ERROR(
"execute query failed in sql_query");
409 NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT)) {
410 ERROR(
"prepare failed in sql_select_query");
418 status = OCIStmtExecute(conn->
ctx, conn->
query, conn->
error, 0, 0, NULL, NULL, OCI_DEFAULT);
419 if (status == OCI_NO_DATA)
goto finish;
420 if (status != OCI_SUCCESS) {
421 ERROR(
"query failed in sql_select_query");
432 if (OCIAttrGet((dvoid *)conn->
query, OCI_HTYPE_STMT, (dvoid *)&conn->
col_count, NULL,
433 OCI_ATTR_PARAM_COUNT, conn->
error))
goto error;
438 MEM(row = talloc_zero_array(conn,
char*, conn->
col_count + 1));
442 status = OCIParamGet(conn->
query, OCI_HTYPE_STMT, conn->
error, (dvoid **)¶m, i + 1);
443 if (status != OCI_SUCCESS) {
444 ERROR(
"OCIParamGet() failed in sql_select_query");
449 status = OCIAttrGet((dvoid*)param, OCI_DTYPE_PARAM, (dvoid*)&dtype, NULL, OCI_ATTR_DATA_TYPE,
451 if (status != OCI_SUCCESS) {
452 ERROR(
"OCIAttrGet() failed in sql_select_query");
473 status = OCIAttrGet((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&dsize, NULL,
474 OCI_ATTR_DATA_SIZE, conn->
error);
475 if (status != OCI_SUCCESS) {
476 ERROR(
"OCIAttrGet() failed in sql_select_query");
481 MEM(row[i] = talloc_zero_array(row,
char, dsize + 1));
491 MEM(row[i] = talloc_zero_array(row,
char, dsize + 1));
505 status = OCIDefineByPos(conn->
query, &
define, conn->
error, i + 1, (ub1 *)row[i], dsize + 1, SQLT_STR,
506 (dvoid *)&
ind[i], NULL, NULL, OCI_DEFAULT);
508 if (status != OCI_SUCCESS) {
509 ERROR(
"OCIDefineByPos() failed in sql_select_query");
532 ub4 size =
sizeof(ub4);
534 OCIAttrGet((CONST dvoid *)conn->
query, OCI_HTYPE_STMT, (dvoid *)&rows, &size, OCI_ATTR_ROW_COUNT, conn->
error);
547 ERROR(
"Socket not connected");
553 query_ctx->
row = NULL;
555 status = OCIStmtFetch(conn->
query, conn->
error, 1, OCI_FETCH_NEXT, OCI_DEFAULT);
556 if (status == OCI_SUCCESS) {
557 query_ctx->
row = conn->
row;
563 if (status == OCI_NO_DATA) {
568 if (status == OCI_ERROR) {
569 ERROR(
"fetch failed in sql_fetch_row");
583 (void) OCIStmtFetch(conn->
query, conn->
error, 0, OCI_FETCH_NEXT, OCI_DEFAULT);
585 TALLOC_FREE(conn->
row);
589 if (OCIStmtRelease (conn->
query, conn->
error, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS ) {
590 ERROR(
"OCI release failed in sql_finish_query");
601 if (OCIStmtRelease(conn->
query, conn->
error, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS ) {
602 ERROR(
"OCI release failed in sql_finish_query");
613 TALLOC_FREE(conn->
row);
617 if (OCIStmtRelease (conn->
query, conn->
error, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS ) {
618 ERROR(
"OCI release failed in sql_finish_query");
629 .name =
"sql_oracle",
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
#define CONF_PARSER_TERMINATOR
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
char const * name1
Name of the CONF_ITEM to parse.
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Defines a CONF_PAIR to C data type mapping.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
CONF_PAIR * cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, fr_token_t op, fr_token_t lhs_quote, fr_token_t rhs_quote)
Allocate a CONF_PAIR.
static fr_time_delta_t timeout
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
main_config_t const * main_config
Main server configuration.
uint32_t max_workers
for the scheduler
module_instance_t * mi
Module instance to detach.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for detach calls.
Temporary structure to hold arguments for instantiation calls.
static const conf_parser_t config[]
rlm_rcode_t
Return codes indicating the result of the module call.
static int instantiate(module_inst_ctx_t const *mctx)
rlm_sql_t const * inst
The rlm_sql instance this connection belongs to.
void * conn
Database specific connection handle.
rlm_sql_t const * inst
Module instance for this query.
char const * query_str
Query string to run.
sql_rcode_t
Action to take at end of an SQL query.
@ RLM_SQL_RECONNECT
Stale connection, should reconnect.
@ RLM_SQL_ERROR
General connection/server error.
@ RLM_SQL_NO_MORE_ROWS
No more rows available.
rlm_sql_handle_t * handle
Connection handle this query is being run on.
rlm_sql_row_t row
Row data from the last query.
sql_rcode_t rcode
Result code.
int col_count
Number of columns associated with the result set.
rlm_sql_driver_t rlm_sql_oracle
static int mod_detach(module_detach_ctx_t const *mctx)
static sql_rcode_t sql_fields(char const **out[], fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
static sql_rcode_t sql_finish_query(fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
static size_t sql_error(TALLOC_CTX *ctx, sql_log_entry_t out[], NDEBUG_UNUSED size_t outlen, fr_sql_query_t *query_ctx, rlm_sql_config_t const *config)
Retrieves any errors associated with the query context.
static sql_rcode_t sql_check_reconnect(rlm_sql_handle_t *handle, rlm_sql_config_t const *config)
uint32_t spool_min
Specifies the minimum number of sessions in the session pool.
ub4 pool_name_len
Length of pool_name in bytes.
uint32_t stmt_cache_size
Statement cache size for each of the sessions in a session pool.
static int max_dflt(CONF_PAIR **out, void *parent, CONF_SECTION *cs, fr_token_t quote, conf_parser_t const *rule)
uint32_t spool_timeout
The sessions idle time (in seconds) (0 disable).
static int _sql_socket_destructor(rlm_sql_oracle_conn_t *conn)
static sql_rcode_t sql_finish_select_query(fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
static unlang_action_t sql_fetch_row(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
uint32_t spool_inc
Specifies the increment for sessions to be started if the current number of sessions are less than se...
uint32_t spool_max
Specifies the maximum number of sessions that can be opened in the session pool.
static int sql_num_rows(fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
static unlang_action_t sql_select_query(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
OCIEnv * env
Number of columns associated with the result set.
OCIError * error
Oracle error handle.
static const conf_parser_t spool_config[]
static const conf_parser_t driver_config[]
char * pool_name
The name of the session pool returned by OCISessionPoolCreate.
static sql_rcode_t sql_free_result(fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
OCISPool * pool
Oracle session pool handle.
static int mod_instantiate(module_inst_ctx_t const *mctx)
static unlang_action_t sql_query(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
static sql_rcode_t sql_socket_init(rlm_sql_handle_t *handle, rlm_sql_config_t const *config, UNUSED fr_time_delta_t timeout)
static int sql_snprint_error(char *out, size_t outlen, rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
Write the last Oracle error out to a buffer.
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
module_instance_t const * parent
Parent module's instance (if any).
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
module_t common
Common fields for all loadable modules.
module_instance_t * driver_submodule
Driver's submodule.
static const char * names[8]
A time delta, a difference in time measured in nanoseconds.
static size_t char ** out