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: dbc618f877e16611086a524dd4e31b384e55c655 $")
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 connection handle
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 handle rlm_sql connection handle.
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  rlm_sql_handle_t *handle, 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), 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->inst->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_bootstrap(module_inst_ctx_t const *mctx)
170 {
171  rlm_sql_t const *parent = talloc_get_type_abort(mctx->inst->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->inst->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->inst->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 -1;
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->dl_inst->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 
312 {
313  int count;
314  rlm_sql_oracle_conn_t *conn = handle->conn;
315 
316  /* get the number of columns in the select list */
317  if (OCIAttrGet((dvoid *)conn->query, OCI_HTYPE_STMT, (dvoid *)&count, NULL, OCI_ATTR_PARAM_COUNT,
318  conn->error)) return -1;
319 
320  return count;
321 }
322 
323 static sql_rcode_t sql_fields(char const **out[], rlm_sql_handle_t *handle, rlm_sql_config_t const *config)
324 {
325  rlm_sql_oracle_conn_t *conn = handle->conn;
326  int fields, i, status;
327  char const **names;
328  OCIParam *param;
329 
330  fields = sql_num_fields(handle, config);
331  if (fields <= 0) return RLM_SQL_ERROR;
332 
333  MEM(names = talloc_array(handle, char const *, fields));
334 
335  for (i = 0; i < fields; i++) {
336  OraText *pcol_name = NULL;
337  ub4 pcol_size = 0;
338 
339  status = OCIParamGet(conn->query, OCI_HTYPE_STMT, conn->error, (dvoid **)&param, i + 1);
340  if (status != OCI_SUCCESS) {
341  ERROR("OCIParamGet(OCI_HTYPE_STMT) failed in sql_fields()");
342  error:
344 
345  return RLM_SQL_ERROR;
346  }
347 
348  status = OCIAttrGet((dvoid **)param, OCI_DTYPE_PARAM, &pcol_name, &pcol_size,
349  OCI_ATTR_NAME, conn->error);
350  if (status != OCI_SUCCESS) {
351  ERROR("OCIParamGet(OCI_ATTR_NAME) failed in sql_fields()");
352 
353  goto error;
354  }
355 
356  names[i] = (char const *)pcol_name;
357  }
358 
359  *out = names;
360 
361  return RLM_SQL_OK;
362 }
363 
364 static sql_rcode_t sql_query(rlm_sql_handle_t *handle, rlm_sql_config_t const *config, char const *query)
365 {
366  int status;
367  rlm_sql_oracle_conn_t *conn = handle->conn;
368 
369  if (!conn->ctx) {
370  ERROR("Socket not connected");
371 
372  return RLM_SQL_RECONNECT;
373  }
374 
375  if (OCIStmtPrepare2(conn->ctx, &conn->query, conn->error, (const OraText *)query, strlen(query),
376  NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT)) {
377  ERROR("prepare failed in sql_query");
378 
379  return RLM_SQL_ERROR;
380  }
381 
382  status = OCIStmtExecute(conn->ctx, conn->query, conn->error, 1, 0,
383  NULL, NULL, OCI_COMMIT_ON_SUCCESS);
384 
385  if (status == OCI_SUCCESS) return RLM_SQL_OK;
386  if (status == OCI_ERROR) {
387  ERROR("execute query failed in sql_query");
388 
389  return sql_check_reconnect(handle, config);
390  }
391 
392  return RLM_SQL_ERROR;
393 }
394 
395 static sql_rcode_t sql_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t const *config, char const *query)
396 {
397  int status;
398  char **row;
399 
400  int i;
401  OCIParam *param;
402  OCIDefine *define;
403 
404  ub2 dtype;
405  ub2 dsize;
406 
407  sb2 *ind;
408 
409  rlm_sql_oracle_conn_t *conn = handle->conn;
410 
411  if (OCIStmtPrepare2(conn->ctx, &conn->query, conn->error, (const OraText *)query, strlen(query),
412  NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT)) {
413  ERROR("prepare failed in sql_select_query");
414 
415  return RLM_SQL_ERROR;
416  }
417 
418  /*
419  * Retrieve a single row
420  */
421  status = OCIStmtExecute(conn->ctx, conn->query, conn->error, 0, 0, NULL, NULL, OCI_DEFAULT);
422  if (status == OCI_NO_DATA) return RLM_SQL_OK;
423  if (status != OCI_SUCCESS) {
424  ERROR("query failed in sql_select_query");
425 
426  return sql_check_reconnect(handle, config);
427  }
428 
429  /*
430  * We only need to do this once per result set, because
431  * the number of columns won't change.
432  */
433  if (conn->col_count == 0) {
434  conn->col_count = sql_num_fields(handle, config);
435 
436  if (conn->col_count == 0) return RLM_SQL_ERROR;
437  }
438 
439  MEM(row = talloc_zero_array(conn, char*, conn->col_count + 1));
440  MEM(ind = talloc_zero_array(row, sb2, conn->col_count + 1));
441 
442  for (i = 0; i < conn->col_count; i++) {
443  status = OCIParamGet(conn->query, OCI_HTYPE_STMT, conn->error, (dvoid **)&param, i + 1);
444  if (status != OCI_SUCCESS) {
445  ERROR("OCIParamGet() failed in sql_select_query");
446 
447  goto error;
448  }
449 
450  status = OCIAttrGet((dvoid*)param, OCI_DTYPE_PARAM, (dvoid*)&dtype, NULL, OCI_ATTR_DATA_TYPE,
451  conn->error);
452  if (status != OCI_SUCCESS) {
453  ERROR("OCIAttrGet() failed in sql_select_query");
454 
455  goto error;
456  }
457 
458  dsize = MAX_DATASTR_LEN;
459 
460  /*
461  * Use the retrieved length of dname to allocate an output buffer, and then define the output
462  * variable (but only for char/string type columns).
463  */
464  switch (dtype) {
465 #ifdef SQLT_AFC
466  case SQLT_AFC: /* ansii fixed char */
467 #endif
468 #ifdef SQLT_AFV
469  case SQLT_AFV: /* ansii var char */
470 #endif
471  case SQLT_VCS: /* var char */
472  case SQLT_CHR: /* char */
473  case SQLT_STR: /* string */
474  status = OCIAttrGet((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&dsize, NULL,
475  OCI_ATTR_DATA_SIZE, conn->error);
476  if (status != OCI_SUCCESS) {
477  ERROR("OCIAttrGet() failed in sql_select_query");
478 
479  goto error;
480  }
481 
482  MEM(row[i] = talloc_zero_array(row, char, dsize + 1));
483 
484  break;
485  case SQLT_DAT:
486  case SQLT_INT:
487  case SQLT_UIN:
488  case SQLT_FLT:
489  case SQLT_PDN:
490  case SQLT_BIN:
491  case SQLT_NUM:
492  MEM(row[i] = talloc_zero_array(row, char, dsize + 1));
493 
494  break;
495  default:
496  dsize = 0;
497  row[i] = NULL;
498  break;
499  }
500 
501  ind[i] = 0;
502 
503  /*
504  * Grab the actual row value and write it to the buffer we allocated.
505  */
506  status = OCIDefineByPos(conn->query, &define, conn->error, i + 1, (ub1 *)row[i], dsize + 1, SQLT_STR,
507  (dvoid *)&ind[i], NULL, NULL, OCI_DEFAULT);
508 
509  if (status != OCI_SUCCESS) {
510  ERROR("OCIDefineByPos() failed in sql_select_query");
511  goto error;
512  }
513  }
514 
515  conn->row = row;
516  conn->ind = ind;
517 
518  return RLM_SQL_OK;
519 
520  error:
521  talloc_free(row);
522 
523  return RLM_SQL_ERROR;
524 }
525 
527 {
528  rlm_sql_oracle_conn_t *conn = handle->conn;
529  ub4 rows = 0;
530  ub4 size = sizeof(ub4);
531 
532  OCIAttrGet((CONST dvoid *)conn->query, OCI_HTYPE_STMT, (dvoid *)&rows, &size, OCI_ATTR_ROW_COUNT, conn->error);
533 
534  return rows;
535 }
536 
538 {
539  int status;
540  rlm_sql_oracle_conn_t *conn = handle->conn;
541 
542  *out = NULL;
543 
544  if (!conn->ctx) {
545  ERROR("Socket not connected");
546 
547  return RLM_SQL_RECONNECT;
548  }
549 
550  handle->row = NULL;
551 
552  status = OCIStmtFetch(conn->query, conn->error, 1, OCI_FETCH_NEXT, OCI_DEFAULT);
553  if (status == OCI_SUCCESS) {
554  *out = handle->row = conn->row;
555 
556  return RLM_SQL_OK;
557  }
558 
559  if (status == OCI_NO_DATA) {
560  handle->row = 0;
561 
562  return RLM_SQL_NO_MORE_ROWS;
563  }
564 
565  if (status == OCI_ERROR) {
566  ERROR("fetch failed in sql_fetch_row");
567  return sql_check_reconnect(handle, config);
568  }
569 
570  return RLM_SQL_ERROR;
571 }
572 
574 {
575  rlm_sql_oracle_conn_t *conn = handle->conn;
576 
577  /* Cancel the cursor first */
578  (void) OCIStmtFetch(conn->query, conn->error, 0, OCI_FETCH_NEXT, OCI_DEFAULT);
579 
580  TALLOC_FREE(conn->row);
581  conn->ind = NULL; /* ind is a child of row */
582  conn->col_count = 0;
583 
584  if (OCIStmtRelease (conn->query, conn->error, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS ) {
585  ERROR("OCI release failed in sql_finish_query");
586  return RLM_SQL_ERROR;
587  }
588 
589  return RLM_SQL_OK;
590 }
591 
593 {
594  rlm_sql_oracle_conn_t *conn = handle->conn;
595 
596  if (OCIStmtRelease(conn->query, conn->error, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS ) {
597  ERROR("OCI release failed in sql_finish_query");
598  return RLM_SQL_ERROR;
599  }
600 
601  return 0;
602 }
603 
605 {
606  rlm_sql_oracle_conn_t *conn = handle->conn;
607 
608  TALLOC_FREE(conn->row);
609  conn->ind = NULL; /* ind is a child of row */
610  conn->col_count = 0;
611 
612  if (OCIStmtRelease (conn->query, conn->error, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS ) {
613  ERROR("OCI release failed in sql_finish_query");
614  return RLM_SQL_ERROR;
615  }
616 
617  return 0;
618 }
619 
621 {
622  return sql_num_rows(handle, config);
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),
633  .bootstrap = mod_bootstrap,
634  .detach = mod_detach
635  },
636  .number = 5,
637  .sql_socket_init = sql_socket_init,
638  .sql_query = sql_query,
639  .sql_select_query = sql_select_query,
640  .sql_num_fields = sql_num_fields,
641  .sql_num_rows = sql_num_rows,
642  .sql_affected_rows = sql_affected_rows,
643  .sql_fetch_row = sql_fetch_row,
644  .sql_fields = sql_fields,
645  .sql_free_result = sql_free_result,
646  .sql_error = sql_error,
647  .sql_finish_query = sql_finish_query,
648  .sql_finish_select_query = sql_finish_select_query
649 };
#define define
#define RCSID(id)
Definition: build.h:444
#define NDEBUG_UNUSED
Definition: build.h:324
#define DIAG_ON(_x)
Definition: build.h:419
#define UNUSED
Definition: build.h:313
#define DIAG_OFF(_x)
Definition: build.h:418
#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:970
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:1220
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
static fr_time_delta_t timeout
Definition: dhcpclient.c:54
void *_CONST data
Module instance's parsed configuration.
Definition: dl_module.h:165
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:65
CONF_SECTION *_CONST conf
Module's instance configuration.
Definition: dl_module.h:166
dl_module_inst_t const * inst
Definition: dl_module.h:87
dl_module_inst_t const *_CONST parent
Parent module's instance (if any).
Definition: dl_module.h:167
#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
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:51
static const conf_parser_t config[]
Definition: base.c:188
#define DEBUG2(fmt,...)
Definition: radclient.h:43
rlm_sql_t const * inst
The rlm_sql instance this connection belongs to.
Definition: rlm_sql.h:103
void * conn
Database specific connection handle.
Definition: rlm_sql.h:101
sql_rcode_t
Action to take at end of an SQL query.
Definition: rlm_sql.h:42
@ RLM_SQL_RECONNECT
Stale connection, should reconnect.
Definition: rlm_sql.h:46
@ RLM_SQL_ERROR
General connection/server error.
Definition: rlm_sql.h:44
@ RLM_SQL_OK
Success.
Definition: rlm_sql.h:45
@ RLM_SQL_NO_MORE_ROWS
No more rows available.
Definition: rlm_sql.h:48
char ** rlm_sql_row_t
Definition: rlm_sql.h:57
rlm_sql_row_t row
Row data from the last query.
Definition: rlm_sql.h:102
Definition: rlm_sql.h:59
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_fetch_row(rlm_sql_row_t *out, 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)
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
static int mod_bootstrap(module_inst_ctx_t const *mctx)
static sql_rcode_t sql_free_result(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
uint32_t spool_max
Specifies the maximum number of sessions that can be opened in the session pool.
static sql_rcode_t sql_finish_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
OCIEnv * env
Number of columns associated with the result set.
OCIError * error
Oracle error handle.
static const conf_parser_t spool_config[]
static int sql_affected_rows(rlm_sql_handle_t *handle, rlm_sql_config_t const *config)
static int sql_num_rows(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
static sql_rcode_t sql_fields(char const **out[], rlm_sql_handle_t *handle, rlm_sql_config_t const *config)
static const conf_parser_t driver_config[]
static sql_rcode_t sql_finish_select_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
char * pool_name
The name of the session pool returned by OCISessionPoolCreate.
static sql_rcode_t sql_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t const *config, char const *query)
static int sql_check_reconnect(rlm_sql_handle_t *handle, rlm_sql_config_t const *config)
OCISPool * pool
Oracle session pool handle.
static int sql_num_fields(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
static sql_rcode_t sql_query(rlm_sql_handle_t *handle, rlm_sql_config_t const *config, char const *query)
static size_t sql_error(TALLOC_CTX *ctx, sql_log_entry_t out[], NDEBUG_UNUSED size_t outlen, rlm_sql_handle_t *handle, rlm_sql_config_t const *config)
Retrieves any errors associated with the connection handle.
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.
dl_module_inst_t * dl_inst
Structure containing the module's instance data, configuration, and dl handle.
Definition: module.h:183
return count
Definition: module.c:175
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:148
module_instance_t * driver_submodule
Driver's submodule.
Definition: rlm_sql.h:185
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