The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
rlm_sql_oracle.c
Go to the documentation of this file.
1 /*
2  * sql_oracle.c Oracle (OCI) routines for rlm_sql
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  * @copyright 2019 Robert Biktimirov (pobept@gmail.com)
19  * @copyright 2000,2006 The FreeRADIUS server project
20  * @copyright 2000 David Kerry (davidk@snti.com)
21  */
22 
23 RCSID("$Id: 0a2c57e48d029dd28b322a3c4d9cd8f09b337b10 $")
24 
25 #define LOG_PREFIX "sql - oracle"
26 
27 #include <freeradius-devel/server/base.h>
28 #include <freeradius-devel/util/debug.h>
29 
30 #include <sys/stat.h>
31 
32 /*
33  * There are typos in the Oracle Instaclient where the definition controlling prototype
34  * format is _STDC_ (not __STDC__).
35  *
36  * There are still cases where the oracle headers do not declare ANSI C function types
37  * but this at least cuts down the errors.
38  *
39  * -Wno-strict-prototypes does the rest.
40  */
41 DIAG_OFF(unused-macros)
42 #if defined(__STDC__) && __STDC__
43 # define _STDC_
44 #endif
45 
46 #include <oci.h>
47 DIAG_ON(unused-macros)
48 
49 #include "rlm_sql.h"
50 
51 static int max_dflt(CONF_PAIR **out, void *parent, CONF_SECTION *cs, fr_token_t quote, conf_parser_t const *rule);
52 
53 typedef struct {
54  OCIEnv *env; //!< Number of columns associated with the result set
55  OCIError *error; //!< Oracle error handle
56  OCISPool *pool; //!< Oracle session pool handle
57  char *pool_name; //!< The name of the session pool returned by OCISessionPoolCreate
58  ub4 pool_name_len; //!< Length of pool_name in bytes.
59 
60  uint32_t stmt_cache_size; //!< Statement cache size for each of the sessions in a session pool
61  uint32_t spool_timeout; //!< The sessions idle time (in seconds) (0 disable).
62  uint32_t spool_min; //!< Specifies the minimum number of sessions in the session pool.
63  uint32_t spool_max; //!< Specifies the maximum number of sessions that can be opened in the session pool
64  uint32_t spool_inc; //!< Specifies the increment for sessions to be started if the current number of sessions are less than sessMax
66 
67 typedef struct {
68  OCIStmt *query;
69  OCIError *error;
70  OCISvcCtx *ctx;
71  sb2 *ind;
72  char **row;
73  int id;
74  int col_count; //!< Number of columns associated with the result set
76 
77 static const conf_parser_t spool_config[] = {
78  { FR_CONF_OFFSET("stmt_cache_size", rlm_sql_oracle_t, stmt_cache_size), .dflt = "32" },
79  { FR_CONF_OFFSET("timeout", rlm_sql_oracle_t, spool_timeout), .dflt = "0" },
80  { FR_CONF_OFFSET("min", rlm_sql_oracle_t, spool_min), .dflt = "1" },
81  { FR_CONF_OFFSET("max", rlm_sql_oracle_t, spool_max), .dflt_func = max_dflt },
82  { FR_CONF_OFFSET("inc", rlm_sql_oracle_t, spool_inc), .dflt = "1" },
84 };
85 
86 static const conf_parser_t driver_config[] = {
87  { FR_CONF_POINTER("spool", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) spool_config },
89 };
90 
91 static int max_dflt(CONF_PAIR **out, UNUSED void *parent, CONF_SECTION *cs, fr_token_t quote, conf_parser_t const *rule)
92 {
93  char *strvalue;
94 
95  strvalue = talloc_asprintf(NULL, "%u", main_config->max_workers);
96  *out = cf_pair_alloc(cs, rule->name1, strvalue, T_OP_EQ, T_BARE_WORD, quote);
97  talloc_free(strvalue);
98 
99  return 0;
100 }
101 
102 #define MAX_DATASTR_LEN 64
103 
104 /** Write the last Oracle error out to a buffer
105  *
106  * @param out Where to write the error (should be at least 512 bytes).
107  * @param outlen The length of the error buffer.
108  * @param handle sql handle.
109  * @param config Instance config.
110  * @return
111  * - 0 on success.
112  * - -1 if there was no error.
113  */
114 static int sql_snprint_error(char *out, size_t outlen, rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
115 {
116  sb4 errcode = 0;
117  rlm_sql_oracle_conn_t *conn = handle->conn;
118 
119  fr_assert(conn);
120 
121  out[0] = '\0';
122 
123  OCIErrorGet((dvoid *) conn->error, 1, (OraText *) NULL, &errcode, (OraText *) out,
124  outlen, OCI_HTYPE_ERROR);
125  if (!errcode) return -1;
126 
127  return 0;
128 }
129 
130 /** Retrieves any errors associated with the query context
131  *
132  * @note Caller will free any memory allocated in ctx.
133  *
134  * @param ctx to allocate temporary error buffers in.
135  * @param out Array of sql_log_entrys to fill.
136  * @param outlen Length of out array.
137  * @param query_ctx Query context to retrieve error for.
138  * @param config rlm_sql config.
139  * @return number of errors written to the #sql_log_entry_t array.
140  */
141 static size_t sql_error(TALLOC_CTX *ctx, sql_log_entry_t out[], NDEBUG_UNUSED size_t outlen,
142  fr_sql_query_t *query_ctx, rlm_sql_config_t const *config)
143 {
144  char errbuff[512];
145  int ret;
146 
147  fr_assert(outlen > 0);
148 
149  ret = sql_snprint_error(errbuff, sizeof(errbuff), query_ctx->handle, config);
150  if (ret < 0) return 0;
151 
152  out[0].type = L_ERR;
153  out[0].msg = talloc_strdup(ctx, errbuff);
154 
155  return 1;
156 }
157 
158 static int mod_detach(module_detach_ctx_t const *mctx)
159 {
160  rlm_sql_oracle_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_sql_oracle_t);
161 
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);
165 
166  return 0;
167 }
168 
169 static int mod_instantiate(module_inst_ctx_t const *mctx)
170 {
171  rlm_sql_t const *parent = talloc_get_type_abort(mctx->mi->parent->data, rlm_sql_t);
172  rlm_sql_config_t const *config = &parent->config;
173  rlm_sql_oracle_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_sql_oracle_t);
174  char errbuff[512];
175  sb4 errcode = 0;
176  OraText *sql_password = NULL;
177  OraText *sql_login = NULL;
178 
179  if (!cf_section_find(mctx->mi->conf, "spool", NULL)) {
180  ERROR("Couldn't load mctx->configuration of session pool(\"spool\" section in driver mctx->config)");
181  return RLM_SQL_ERROR;
182  }
183 
184  /*
185  * Initialises the oracle environment
186  */
187  if (OCIEnvCreate(&inst->env, OCI_DEFAULT | OCI_THREADED, NULL, NULL, NULL, NULL, 0, NULL)) {
188  ERROR("Couldn't init Oracle OCI environment (OCIEnvCreate())");
189 
190  return RLM_SQL_ERROR;
191  }
192 
193  /*
194  * Allocates an error handle
195  */
196  if (OCIHandleAlloc((dvoid *)inst->env, (dvoid **)&inst->error, OCI_HTYPE_ERROR, 0, NULL)) {
197  ERROR("Couldn't init Oracle ERROR handle (OCIHandleAlloc())");
198 
199  return RLM_SQL_ERROR;
200  }
201 
202  /*
203  * Allocates an session pool handle
204  */
205  if (OCIHandleAlloc((dvoid *)inst->env, (dvoid **)&inst->pool, OCI_HTYPE_SPOOL, 0, NULL)) {
206  ERROR("Couldn't init Oracle session pool (OCIHandleAlloc())");
207  return RLM_SQL_ERROR;
208  }
209 
210  /*
211  * Create session pool
212  */
213  DEBUG2("OCISessionPoolCreate min=%d max=%d inc=%d", inst->spool_min, inst->spool_max, inst->spool_inc);
214 
215  /* We need it to fix const issues between 'const char *' vs 'unsigned char *' */
216  memcpy(&sql_login, &config->sql_login, sizeof(sql_login));
217  memcpy(&sql_password, &config->sql_password, sizeof(sql_password));
218 
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),
222  inst->spool_min, inst->spool_max, inst->spool_inc,
223  sql_login, strlen(config->sql_login),
224  sql_password, strlen(config->sql_password),
225  OCI_SPC_STMTCACHE | OCI_SPC_HOMOGENEOUS)) {
226 
227  errbuff[0] = '\0';
228  OCIErrorGet((dvoid *) inst->error, 1, (OraText *) NULL, &errcode, (OraText *) errbuff,
229  sizeof(errbuff), OCI_HTYPE_ERROR);
230  if (!errcode) return RLM_SQL_ERROR;
231 
232  ERROR("Oracle create session pool failed: '%s'", errbuff);
233  return RLM_SQL_ERROR;
234  }
235 
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");
240  return RLM_SQL_ERROR;
241  }
242  }
243 
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");
247  return RLM_SQL_ERROR;
248  }
249 
250  return 0;
251 }
252 
254 {
255  char errbuff[512];
256 
257  if (sql_snprint_error(errbuff, sizeof(errbuff), handle, config) < 0) return -1;
258 
259  if (strstr(errbuff, "ORA-03113") || strstr(errbuff, "ORA-03114")) {
260  ERROR("OCI_SERVER_NOT_CONNECTED");
261  return RLM_SQL_RECONNECT;
262  }
263 
264  return RLM_SQL_ERROR;
265 }
266 
268 {
269  if (conn->ctx) OCISessionRelease(conn->ctx, conn->error, NULL, 0, OCI_DEFAULT);
270  if (conn->error) OCIHandleFree((dvoid *)conn->error, OCI_HTYPE_ERROR);
271  return 0;
272 }
273 
276 {
277  char errbuff[512];
278 
279  rlm_sql_oracle_t *inst = talloc_get_type_abort(handle->inst->driver_submodule->data, rlm_sql_oracle_t);
280  rlm_sql_oracle_conn_t *conn;
281 
282  MEM(conn = handle->conn = talloc_zero(handle, rlm_sql_oracle_conn_t));
283  talloc_set_destructor(conn, _sql_socket_destructor);
284 
285  /*
286  * Allocates an error handle
287  */
288  if (OCIHandleAlloc((dvoid *)inst->env, (dvoid **)&conn->error, OCI_HTYPE_ERROR, 0, NULL)) {
289  ERROR("Couldn't init Oracle ERROR handle (OCIHandleAlloc())");
290 
291  return RLM_SQL_ERROR;
292  }
293 
294  /*
295  * Get session from pool
296  */
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'",
302  inst->pool_name,
303  (sql_snprint_error(errbuff, sizeof(errbuff), handle, config) == 0) ? errbuff : "unknown");
304 
305  return RLM_SQL_ERROR;
306  }
307 
308  return RLM_SQL_OK;
309 }
310 
311 static sql_rcode_t sql_fields(char const **out[], fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
312 {
313  rlm_sql_oracle_conn_t *conn = query_ctx->handle->conn;
314  int fields, i, status;
315  char const **names;
316  OCIParam *param;
317 
318  if (OCIAttrGet((dvoid *)conn->query, OCI_HTYPE_STMT, (dvoid *)&fields, NULL, OCI_ATTR_PARAM_COUNT,
319  conn->error)) return RLM_SQL_ERROR;
320  if (fields == 0) return RLM_SQL_ERROR;
321 
322  MEM(names = talloc_array(query_ctx, char const *, fields));
323 
324  for (i = 0; i < fields; i++) {
325  OraText *pcol_name = NULL;
326  ub4 pcol_size = 0;
327 
328  status = OCIParamGet(conn->query, OCI_HTYPE_STMT, conn->error, (dvoid **)&param, i + 1);
329  if (status != OCI_SUCCESS) {
330  ERROR("OCIParamGet(OCI_HTYPE_STMT) failed in sql_fields()");
331  error:
333 
334  return RLM_SQL_ERROR;
335  }
336 
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()");
341 
342  goto error;
343  }
344 
345  names[i] = (char const *)pcol_name;
346  }
347 
348  *out = names;
349 
350  return RLM_SQL_OK;
351 }
352 
353 static unlang_action_t sql_query(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
354 {
355  fr_sql_query_t *query_ctx = talloc_get_type_abort(uctx, fr_sql_query_t);
356  int status;
357  rlm_sql_oracle_conn_t *conn = query_ctx->handle->conn;
358 
359  if (!conn->ctx) {
360  ERROR("Socket not connected");
361 
362  query_ctx->rcode = RLM_SQL_RECONNECT;
364  }
365 
366  query_ctx->rcode = RLM_SQL_ERROR;
367 
368  if (OCIStmtPrepare2(conn->ctx, &conn->query, conn->error, (const OraText *)query_ctx->query_str, strlen(query_ctx->query_str),
369  NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT)) {
370  ERROR("prepare failed in sql_query");
371 
373  }
374 
375  status = OCIStmtExecute(conn->ctx, conn->query, conn->error, 1, 0,
376  NULL, NULL, OCI_COMMIT_ON_SUCCESS);
377 
378  if (status == OCI_SUCCESS) {
379  query_ctx->rcode = RLM_SQL_OK;
381  }
382  if (status == OCI_ERROR) {
383  ERROR("execute query failed in sql_query");
384 
385  query_ctx->rcode = sql_check_reconnect(query_ctx->handle, &query_ctx->inst->config);
386  }
387 
389 }
390 
391 static unlang_action_t sql_select_query(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
392 {
393  fr_sql_query_t *query_ctx = talloc_get_type_abort(uctx, fr_sql_query_t);
394  int status;
395  char **row = NULL;
396 
397  int i;
398  OCIParam *param;
399  OCIDefine *define;
400 
401  ub2 dtype;
402  ub2 dsize;
403 
404  sb2 *ind;
405 
406  rlm_sql_oracle_conn_t *conn = query_ctx->handle->conn;
407 
408  if (OCIStmtPrepare2(conn->ctx, &conn->query, conn->error, (const OraText *)query_ctx->query_str, strlen(query_ctx->query_str),
409  NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT)) {
410  ERROR("prepare failed in sql_select_query");
411 
412  goto error;
413  }
414 
415  /*
416  * Retrieve a single row
417  */
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");
422 
423  query_ctx->rcode = sql_check_reconnect(query_ctx->handle, &query_ctx->inst->config);
425  }
426 
427  /*
428  * We only need to do this once per result set, because
429  * the number of columns won't change.
430  */
431  if (conn->col_count == 0) {
432  if (OCIAttrGet((dvoid *)conn->query, OCI_HTYPE_STMT, (dvoid *)&conn->col_count, NULL,
433  OCI_ATTR_PARAM_COUNT, conn->error)) goto error;
434 
435  if (conn->col_count == 0) goto error;
436  }
437 
438  MEM(row = talloc_zero_array(conn, char*, conn->col_count + 1));
439  MEM(ind = talloc_zero_array(row, sb2, conn->col_count + 1));
440 
441  for (i = 0; i < conn->col_count; i++) {
442  status = OCIParamGet(conn->query, OCI_HTYPE_STMT, conn->error, (dvoid **)&param, i + 1);
443  if (status != OCI_SUCCESS) {
444  ERROR("OCIParamGet() failed in sql_select_query");
445 
446  goto error;
447  }
448 
449  status = OCIAttrGet((dvoid*)param, OCI_DTYPE_PARAM, (dvoid*)&dtype, NULL, OCI_ATTR_DATA_TYPE,
450  conn->error);
451  if (status != OCI_SUCCESS) {
452  ERROR("OCIAttrGet() failed in sql_select_query");
453 
454  goto error;
455  }
456 
457  dsize = MAX_DATASTR_LEN;
458 
459  /*
460  * Use the retrieved length of dname to allocate an output buffer, and then define the output
461  * variable (but only for char/string type columns).
462  */
463  switch (dtype) {
464 #ifdef SQLT_AFC
465  case SQLT_AFC: /* ansii fixed char */
466 #endif
467 #ifdef SQLT_AFV
468  case SQLT_AFV: /* ansii var char */
469 #endif
470  case SQLT_VCS: /* var char */
471  case SQLT_CHR: /* char */
472  case SQLT_STR: /* string */
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");
477 
478  goto error;
479  }
480 
481  MEM(row[i] = talloc_zero_array(row, char, dsize + 1));
482 
483  break;
484  case SQLT_DAT:
485  case SQLT_INT:
486  case SQLT_UIN:
487  case SQLT_FLT:
488  case SQLT_PDN:
489  case SQLT_BIN:
490  case SQLT_NUM:
491  MEM(row[i] = talloc_zero_array(row, char, dsize + 1));
492 
493  break;
494  default:
495  dsize = 0;
496  row[i] = NULL;
497  break;
498  }
499 
500  ind[i] = 0;
501 
502  /*
503  * Grab the actual row value and write it to the buffer we allocated.
504  */
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);
507 
508  if (status != OCI_SUCCESS) {
509  ERROR("OCIDefineByPos() failed in sql_select_query");
510  goto error;
511  }
512  }
513 
514  conn->row = row;
515  conn->ind = ind;
516 
517 finish:
518  query_ctx->rcode = RLM_SQL_OK;
520 
521  error:
522  talloc_free(row);
523 
524  query_ctx->rcode = RLM_SQL_ERROR;
526 }
527 
529 {
530  rlm_sql_oracle_conn_t *conn = query_ctx->handle->conn;
531  ub4 rows = 0;
532  ub4 size = sizeof(ub4);
533 
534  OCIAttrGet((CONST dvoid *)conn->query, OCI_HTYPE_STMT, (dvoid *)&rows, &size, OCI_ATTR_ROW_COUNT, conn->error);
535 
536  return rows;
537 }
538 
539 static unlang_action_t sql_fetch_row(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
540 {
541  fr_sql_query_t *query_ctx = talloc_get_type_abort(uctx, fr_sql_query_t);
542  int status;
543  rlm_sql_handle_t *handle = query_ctx->handle;
544  rlm_sql_oracle_conn_t *conn = handle->conn;
545 
546  if (!conn->ctx) {
547  ERROR("Socket not connected");
548 
549  query_ctx->rcode = RLM_SQL_RECONNECT;
551  }
552 
553  query_ctx->row = NULL;
554 
555  status = OCIStmtFetch(conn->query, conn->error, 1, OCI_FETCH_NEXT, OCI_DEFAULT);
556  if (status == OCI_SUCCESS) {
557  query_ctx->row = conn->row;
558 
559  query_ctx->rcode = RLM_SQL_OK;
561  }
562 
563  if (status == OCI_NO_DATA) {
564  query_ctx->rcode = RLM_SQL_NO_MORE_ROWS;
566  }
567 
568  if (status == OCI_ERROR) {
569  ERROR("fetch failed in sql_fetch_row");
570  query_ctx->rcode = sql_check_reconnect(handle, &query_ctx->inst->config);
572  }
573 
574  query_ctx->rcode = RLM_SQL_ERROR;
576 }
577 
579 {
580  rlm_sql_oracle_conn_t *conn = query_ctx->handle->conn;
581 
582  /* Cancel the cursor first */
583  (void) OCIStmtFetch(conn->query, conn->error, 0, OCI_FETCH_NEXT, OCI_DEFAULT);
584 
585  TALLOC_FREE(conn->row);
586  conn->ind = NULL; /* ind is a child of row */
587  conn->col_count = 0;
588 
589  if (OCIStmtRelease (conn->query, conn->error, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS ) {
590  ERROR("OCI release failed in sql_finish_query");
591  return RLM_SQL_ERROR;
592  }
593 
594  return RLM_SQL_OK;
595 }
596 
598 {
599  rlm_sql_oracle_conn_t *conn = query_ctx->handle->conn;
600 
601  if (OCIStmtRelease(conn->query, conn->error, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS ) {
602  ERROR("OCI release failed in sql_finish_query");
603  return RLM_SQL_ERROR;
604  }
605 
606  return 0;
607 }
608 
610 {
611  rlm_sql_oracle_conn_t *conn = query_ctx->handle->conn;
612 
613  TALLOC_FREE(conn->row);
614  conn->ind = NULL; /* ind is a child of row */
615  conn->col_count = 0;
616 
617  if (OCIStmtRelease (conn->query, conn->error, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS ) {
618  ERROR("OCI release failed in sql_finish_query");
619  return RLM_SQL_ERROR;
620  }
621 
622  return 0;
623 }
624 
625 /* Exported to rlm_sql */
628  .common = {
629  .name = "sql_oracle",
630  .magic = MODULE_MAGIC_INIT,
631  .inst_size = sizeof(rlm_sql_oracle_t),
634  .detach = mod_detach
635  },
636  .sql_socket_init = sql_socket_init,
637  .sql_query = sql_query,
638  .sql_select_query = sql_select_query,
639  .sql_num_rows = sql_num_rows,
640  .sql_affected_rows = sql_num_rows,
641  .sql_fetch_row = sql_fetch_row,
642  .sql_fields = sql_fields,
643  .sql_free_result = sql_free_result,
644  .sql_error = sql_error,
645  .sql_finish_query = sql_finish_query,
646  .sql_finish_select_query = sql_finish_select_query
647 };
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
#define define
#define RCSID(id)
Definition: build.h:446
#define NDEBUG_UNUSED
Definition: build.h:324
#define DIAG_ON(_x)
Definition: build.h:421
#define UNUSED
Definition: build.h:313
#define DIAG_OFF(_x)
Definition: build.h:420
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:626
#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
Definition: cf_parse.h:268
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
Definition: cf_parse.h:310
char const * name1
Name of the CONF_ITEM to parse.
Definition: cf_parse.h:564
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition: cf_parse.h:400
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
Configuration AVP similar to a fr_pair_t.
Definition: cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition: cf_util.c:1030
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.
Definition: cf_util.c:1281
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
static fr_time_delta_t timeout
Definition: dhcpclient.c:54
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:63
#define ind(mm, x)
Definition: isaac.c:18
talloc_free(reap)
@ L_ERR
Error message.
Definition: log.h:56
main_config_t const * main_config
Main server configuration.
Definition: main_config.c:69
uint32_t max_workers
for the scheduler
Definition: main_config.h:151
unsigned int uint32_t
Definition: merged_model.c:33
module_instance_t * mi
Module instance to detach.
Definition: module_ctx.h:57
module_instance_t * mi
Instance of the module being instantiated.
Definition: module_ctx.h:51
Temporary structure to hold arguments for detach calls.
Definition: module_ctx.h:56
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:50
static const conf_parser_t config[]
Definition: base.c:188
#define DEBUG2(fmt,...)
Definition: radclient.h:43
#define RETURN_MODULE_OK
Definition: rcode.h:57
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
static int instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_rest.c:1329
rlm_sql_t const * inst
The rlm_sql instance this connection belongs to.
Definition: rlm_sql.h:115
void * conn
Database specific connection handle.
Definition: rlm_sql.h:114
rlm_sql_t const * inst
Module instance for this query.
Definition: rlm_sql.h:137
char const * query_str
Query string to run.
Definition: rlm_sql.h:143
sql_rcode_t
Action to take at end of an SQL query.
Definition: rlm_sql.h:44
@ RLM_SQL_RECONNECT
Stale connection, should reconnect.
Definition: rlm_sql.h:48
@ RLM_SQL_ERROR
General connection/server error.
Definition: rlm_sql.h:46
@ RLM_SQL_OK
Success.
Definition: rlm_sql.h:47
@ RLM_SQL_NO_MORE_ROWS
No more rows available.
Definition: rlm_sql.h:50
rlm_sql_handle_t * handle
Connection handle this query is being run on.
Definition: rlm_sql.h:139
rlm_sql_row_t row
Row data from the last query.
Definition: rlm_sql.h:147
sql_rcode_t rcode
Result code.
Definition: rlm_sql.h:146
Definition: rlm_sql.h:61
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...
#define MAX_DATASTR_LEN
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.
Definition: module.h:329
void * data
Module's instance data.
Definition: module.h:271
module_instance_t const * parent
Parent module's instance (if any).
Definition: module.h:337
RETURN_MODULE_FAIL
fr_assert(0)
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.
Definition: rlm_sql.h:202
module_instance_t * driver_submodule
Driver's submodule.
Definition: rlm_sql.h:243
rlm_sql_config_t config
Definition: rlm_sql.h:236
static const char * names[8]
Definition: time.c:617
A time delta, a difference in time measured in nanoseconds.
Definition: time.h:80
enum fr_token fr_token_t
@ T_BARE_WORD
Definition: token.h:120
@ T_OP_EQ
Definition: token.h:83
static fr_slen_t parent
Definition: pair.h:844
static size_t char ** out
Definition: value.h:984