The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
rlm_sql_postgresql.c
Go to the documentation of this file.
1 /*
2  * sql_postgresql.c Postgresql rlm_sql driver
3  *
4  * Version: $Id: b1c577895c2adca06b3802aa5722de7f3eed29b1 $
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * @copyright 2000,2006 The FreeRADIUS server project
21  * @copyright 2000 Mike Machado (mike@innercite.com)
22  * @copyright 2000 Alan DeKok (aland@freeradius.org)
23  */
24 
25 /*
26  * April 2001:
27  *
28  * Use blocking queries and delete unused functions. In
29  * rlm_sql_postgresql replace all functions that are not really used
30  * with the not_implemented function.
31  *
32  * Add a new field to the rlm_sql_postgres_conn_t struct to store the
33  * number of rows affected by a query because the sql module calls
34  * finish_query before it retrieves the number of affected rows from the
35  * driver
36  *
37  * Bernhard Herzog <bh@intevation.de>
38  */
39 
40 RCSID("$Id: b1c577895c2adca06b3802aa5722de7f3eed29b1 $")
41 
42 #define LOG_PREFIX "sql - postgresql"
43 
44 #include <freeradius-devel/server/base.h>
45 #include <freeradius-devel/util/debug.h>
46 
47 #include <sys/stat.h>
48 
49 #include <libpq-fe.h>
50 #include <postgres_ext.h>
51 
52 #include "config.h"
53 #include "rlm_sql.h"
54 
55 #ifndef NAMEDATALEN
56 # define NAMEDATALEN 64
57 #endif
58 
59 /** PostgreSQL configuration
60  *
61  */
62 typedef struct {
63  char const *db_string; //!< Text based configuration string.
64  bool send_application_name; //!< Whether we send the application name to PostgreSQL.
65  fr_trie_t *states; //!< sql state trie.
67 
68 typedef struct {
69  PGconn *db;
70  PGresult *result;
71  int cur_row;
74  char **row;
76 
78  { FR_CONF_OFFSET("send_application_name", rlm_sql_postgresql_t, send_application_name), .dflt = "yes" },
80 };
81 
82 /** These are PostgreSQL specific error codes which are not covered in SQL 2011
83  *
84  */
86  { "03", "SQL statement not yet complete", RLM_SQL_OK },
87  { "0B", "Invalid transaction initiation", RLM_SQL_ERROR },
88  { "53", "Insufficient resources", RLM_SQL_ERROR },
89  /*
90  * 54000 program_limit_exceeded
91  * 54001 statement_too_complex
92  * 54011 too_many_columns
93  * 54023 too_many_arguments
94  */
95  { "54", "Program limit exceeded", RLM_SQL_QUERY_INVALID },
96 
97  { "55", "Object not in prerequisite state", RLM_SQL_ERROR },
98 
99  /*
100  * Error seen when NOWAIT is used to abort queries that involve rows
101  * which are already locked.
102  *
103  * Listed specifically for efficiency.
104  */
105  { "55P03", "Lock not available", RLM_SQL_ERROR },
106 
107  { "57", "Operator intervention", RLM_SQL_ERROR },
108 
109  /*
110  * This is really 'statement_timeout' or the error which is returned when
111  * 'statement_timeout' is hit.
112  *
113  * It's unlikely that this has been caused by a connection failure, and
114  * most likely to have been caused by a long running query.
115  *
116  * If the query is persistently long running then the database/query should
117  * be optimised, or 'statement_timeout' should be increased.
118  *
119  * Forcing a reconnect here only eats more resources on the DB so we will
120  * no longer do so as of 3.0.4.
121  */
122  { "57014", "Query cancelled", RLM_SQL_ERROR },
123  { "57P01", "Admin shutdown", RLM_SQL_RECONNECT },
124  { "57P02", "Crash shutdown", RLM_SQL_RECONNECT },
125  { "57P03", "Cannot connect now", RLM_SQL_RECONNECT },
126  { "58", "System error", RLM_SQL_RECONNECT },
127  { "72", "Snapshot failure", RLM_SQL_ERROR },
128  { "F0", "Configuration file error", RLM_SQL_ERROR },
129  { "P0", "PL/PGSQL error", RLM_SQL_ERROR },
130  { "XX", "Internal error", RLM_SQL_ERROR },
131  { NULL, NULL, RLM_SQL_ERROR } /* Default code */
132 };
133 
134 /** Return the number of affected rows of the result as an int instead of the string that postgresql provides
135  *
136  */
137 static int affected_rows(PGresult * result)
138 {
139  return atoi(PQcmdTuples(result));
140 }
141 
142 /** Free the row of the current result that's stored in the conn struct
143  *
144  */
146 {
147  TALLOC_FREE(conn->row);
148  conn->num_fields = 0;
149 }
150 
151 #if defined(PG_DIAG_SQLSTATE) && defined(PG_DIAG_MESSAGE_PRIMARY)
152 static sql_rcode_t sql_classify_error(rlm_sql_postgresql_t *inst, ExecStatusType status, PGresult const *result)
153 {
154  char const *error_code;
155  char const *error_msg;
156  sql_state_entry_t const *entry;
157 
158  error_code = PQresultErrorField(result, PG_DIAG_SQLSTATE);
159  if (!error_code) {
160  switch (status){
161  /*
162  * Successful completion of a command returning no data.
163  */
164  case PGRES_COMMAND_OK:
165  #ifdef HAVE_PGRES_SINGLE_TUPLE
166  case PGRES_SINGLE_TUPLE:
167  #endif
168  case PGRES_TUPLES_OK:
169  #ifdef HAVE_PGRES_COPY_BOTH
170  case PGRES_COPY_BOTH:
171  #endif
172  case PGRES_COPY_OUT:
173  case PGRES_COPY_IN:
174  error_code = "00000";
175  break;
176 
177  case PGRES_EMPTY_QUERY: /* Shouldn't happen */
178  error_code = "42000";
179  break;
180 
181  #ifdef HAVE_PGRES_PIPELINE_SYNC
182  case PGRES_PIPELINE_SYNC:
183  case PGRES_PIPELINE_ABORTED:
184  ERROR("libpq reported aborted pipeline");
185  return RLM_SQL_ERROR;
186  #endif
187 
188  case PGRES_BAD_RESPONSE:
189  case PGRES_NONFATAL_ERROR:
190  case PGRES_FATAL_ERROR:
191  ERROR("libpq provided no error code");
192  return RLM_SQL_ERROR;
193  }
194  }
195 
196  entry = sql_state_entry_find(inst->states, error_code);
197  if (!entry) {
198  ERROR("Can't classify: %s", error_code);
199  return RLM_SQL_ERROR;
200  }
201 
202  DEBUG2("sqlstate %s matched %s: %s (%s)", error_code,
203  entry->sql_state, entry->meaning, fr_table_str_by_value(sql_rcode_table, entry->rcode, "<DEFAULT>"));
204 
205  /*
206  * WARNING error class.
207  */
208  if ((entry->sql_state[0] == '0') && (entry->sql_state[1] == '1')) {
209  error_msg = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY);
210  if (error_msg) WARN("%s", error_msg);
211  }
212 
213  return entry->rcode;
214 }
215 # else
216 static sql_rcode_t sql_classify_error(UNUSED PGresult const *result)
217 {
218  ERROR("Error occurred, no more information available, rebuild with newer libpq");
219  return RLM_SQL_ERROR;
220 }
221 #endif
222 
224 {
225  DEBUG2("Socket destructor called, closing socket");
226 
227  if (!conn->db) return 0;
228 
229  /* PQfinish also frees the memory used by the PGconn structure */
230  PQfinish(conn->db);
231 
232  return 0;
233 }
234 
237 {
238  rlm_sql_postgresql_t *inst = talloc_get_type_abort(handle->inst->driver_submodule->data, rlm_sql_postgresql_t);
240 
241  MEM(conn = handle->conn = talloc_zero(handle, rlm_sql_postgres_conn_t));
242  talloc_set_destructor(conn, _sql_socket_destructor);
243 
244  DEBUG2("Connecting using parameters: %s", inst->db_string);
245  conn->db = PQconnectdb(inst->db_string);
246  if (!conn->db) {
247  ERROR("Connection failed: Out of memory");
248  return -1;
249  }
250  if (PQstatus(conn->db) != CONNECTION_OK) {
251  ERROR("Connection failed: %s", PQerrorMessage(conn->db));
252  PQfinish(conn->db);
253  conn->db = NULL;
254  return -1;
255  }
256 
257  DEBUG2("Connected to database '%s' on '%s' server version %i, protocol version %i, backend PID %i ",
258  PQdb(conn->db), PQhost(conn->db), PQserverVersion(conn->db), PQprotocolVersion(conn->db),
259  PQbackendPID(conn->db));
260 
261  return 0;
262 }
263 
264 static unlang_action_t sql_query(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
265 {
266  fr_sql_query_t *query_ctx = talloc_get_type_abort(uctx, fr_sql_query_t);
267  rlm_sql_postgres_conn_t *conn = query_ctx->handle->conn;
268  rlm_sql_postgresql_t *inst = talloc_get_type_abort(query_ctx->inst->driver_submodule->data, rlm_sql_postgresql_t);
270  fr_time_t start;
271  int sockfd;
272  PGresult *tmp_result;
273  int numfields = 0;
274  ExecStatusType status;
275 
276  if (!conn->db) {
277  ERROR("Socket not connected");
278  reconnect:
279  query_ctx->rcode = RLM_SQL_RECONNECT;
281  }
282 
283  sockfd = PQsocket(conn->db);
284  if (sockfd < 0) {
285  ERROR("Unable to obtain socket: %s", PQerrorMessage(conn->db));
286  goto reconnect;
287  }
288 
289  if (!PQsendQuery(conn->db, query_ctx->query_str)) {
290  ERROR("Failed to send query: %s", PQerrorMessage(conn->db));
291  goto reconnect;
292  }
293 
294  /*
295  * We try to avoid blocking by waiting until the driver indicates that
296  * the result is ready or our timeout expires
297  */
298  start = fr_time();
299  while (PQisBusy(conn->db)) {
300  int r;
301  fd_set read_fd;
302  fr_time_delta_t elapsed = fr_time_delta_wrap(0);
303 
304  FD_ZERO(&read_fd);
305  FD_SET(sockfd, &read_fd);
306 
308  elapsed = fr_time_sub(fr_time(), start);
309  if (fr_time_delta_gteq(elapsed, timeout)) goto too_long;
310  }
311 
312  r = select(sockfd + 1, &read_fd, NULL, NULL, fr_time_delta_ispos(timeout) ?
314  if (r == 0) {
315  too_long:
316  ERROR("Socket read timeout after %d seconds", (int) fr_time_delta_to_sec(timeout));
317  goto reconnect;
318  }
319  if (r < 0) {
320  if (errno == EINTR) continue;
321  ERROR("Failed in select: %s", fr_syserror(errno));
322  goto reconnect;
323  }
324  if (!PQconsumeInput(conn->db)) {
325  ERROR("Failed reading input: %s", PQerrorMessage(conn->db));
326  goto reconnect;
327  }
328  }
329 
330  /*
331  * Returns a PGresult pointer or possibly a null pointer.
332  * A non-null pointer will generally be returned except in
333  * out-of-memory conditions or serious errors such as inability
334  * to send the command to the server. If a null pointer is
335  * returned, it should be treated like a PGRES_FATAL_ERROR
336  * result.
337  */
338  conn->result = PQgetResult(conn->db);
339 
340  /* Discard results for appended queries */
341  while ((tmp_result = PQgetResult(conn->db)) != NULL)
342  PQclear(tmp_result);
343 
344  /*
345  * As this error COULD be a connection error OR an out-of-memory
346  * condition return value WILL be wrong SOME of the time
347  * regardless! Pick your poison...
348  */
349  if (!conn->result) {
350  ERROR("Failed getting query result: %s", PQerrorMessage(conn->db));
351  goto reconnect;
352  }
353 
354  status = PQresultStatus(conn->result);
355  switch (status){
356  /*
357  * Successful completion of a command returning no data.
358  */
359  case PGRES_COMMAND_OK:
360  /*
361  * Affected_rows function only returns the number of affected rows of a command
362  * returning no data...
363  */
364  conn->affected_rows = affected_rows(conn->result);
365  DEBUG2("query affected rows = %i", conn->affected_rows);
366  break;
367  /*
368  * Successful completion of a command returning data (such as a SELECT or SHOW).
369  */
370 #ifdef HAVE_PGRES_SINGLE_TUPLE
371  case PGRES_SINGLE_TUPLE:
372 #endif
373  case PGRES_TUPLES_OK:
374  conn->cur_row = 0;
375  conn->affected_rows = PQntuples(conn->result);
376  numfields = PQnfields(conn->result); /*Check row storing functions..*/
377  DEBUG2("query returned rows = %i, fields = %i", conn->affected_rows, numfields);
378  break;
379 
380 #ifdef HAVE_PGRES_COPY_BOTH
381  case PGRES_COPY_BOTH:
382 #endif
383  case PGRES_COPY_OUT:
384  case PGRES_COPY_IN:
385  DEBUG2("Data transfer started");
386  break;
387 
388  /*
389  * Weird.. this shouldn't happen.
390  */
391  case PGRES_EMPTY_QUERY:
392  case PGRES_BAD_RESPONSE: /* The server's response was not understood */
393  case PGRES_NONFATAL_ERROR:
394  case PGRES_FATAL_ERROR:
395 #ifdef HAVE_PGRES_PIPELINE_SYNC
396  case PGRES_PIPELINE_SYNC:
397  case PGRES_PIPELINE_ABORTED:
398 #endif
399  break;
400  }
401 
402  query_ctx->rcode = sql_classify_error(inst, status, conn->result);
403  if (query_ctx->rcode != RLM_SQL_OK) RETURN_MODULE_FAIL;
405 }
406 
407 static sql_rcode_t sql_fields(char const **out[], fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
408 {
409  rlm_sql_postgres_conn_t *conn = query_ctx->handle->conn;
410 
411  int fields, i;
412  char const **names;
413 
414  fields = PQnfields(conn->result);
415  if (fields <= 0) return RLM_SQL_ERROR;
416 
417  MEM(names = talloc_array(query_ctx, char const *, fields));
418 
419  for (i = 0; i < fields; i++) names[i] = PQfname(conn->result, i);
420  *out = names;
421 
422  return RLM_SQL_OK;
423 }
424 
425 static unlang_action_t sql_fetch_row(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
426 {
427  fr_sql_query_t *query_ctx = talloc_get_type_abort(uctx, fr_sql_query_t);
428  rlm_sql_handle_t *handle = query_ctx->handle;
429  int records, i, len;
430  rlm_sql_postgres_conn_t *conn = handle->conn;
431 
432  query_ctx->row = NULL;
433 
434  query_ctx->rcode = RLM_SQL_NO_MORE_ROWS;
435  if (conn->cur_row >= PQntuples(conn->result)) RETURN_MODULE_OK;
436 
437  free_result_row(conn);
438 
439  records = PQnfields(conn->result);
440  conn->num_fields = records;
441 
442  if ((PQntuples(conn->result) > 0) && (records > 0)) {
443  conn->row = talloc_zero_array(conn, char *, records + 1);
444  for (i = 0; i < records; i++) {
445  len = PQgetlength(conn->result, conn->cur_row, i);
446  conn->row[i] = talloc_array(conn->row, char, len + 1);
447  strlcpy(conn->row[i], PQgetvalue(conn->result, conn->cur_row, i), len + 1);
448  }
449  conn->cur_row++;
450  query_ctx->row = conn->row;
451 
452  query_ctx->rcode = RLM_SQL_OK;
453  }
454 
456 }
457 
459 {
460  rlm_sql_postgres_conn_t *conn = query_ctx->handle->conn;
461 
462  if (conn->result != NULL) {
463  PQclear(conn->result);
464  conn->result = NULL;
465  }
466 
467  free_result_row(conn);
468 
469  return 0;
470 }
471 
472 /** Retrieves any errors associated with the query context
473  *
474  * @note Caller will free any memory allocated in ctx.
475  *
476  * @param ctx to allocate temporary error buffers in.
477  * @param out Array of sql_log_entrys to fill.
478  * @param outlen Length of out array.
479  * @param query_ctx Query context to retrieve error for.
480  * @param config rlm_sql config.
481  * @return number of errors written to the #sql_log_entry_t array.
482  */
483 static size_t sql_error(TALLOC_CTX *ctx, sql_log_entry_t out[], size_t outlen,
484  fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
485 {
486  rlm_sql_postgres_conn_t *conn = query_ctx->handle->conn;
487  char const *p, *q;
488  size_t i = 0;
489 
490  fr_assert(outlen > 0);
491 
492  p = PQerrorMessage(conn->db);
493  while ((q = strchr(p, '\n'))) {
494  out[i].type = L_ERR;
495  out[i].msg = talloc_typed_asprintf(ctx, "%.*s", (int) (q - p), p);
496  p = q + 1;
497  if (++i == outlen) return outlen;
498  }
499  if (*p != '\0') {
500  out[i].type = L_ERR;
501  out[i].msg = p;
502  i++;
503  }
504 
505  return i;
506 }
507 
509 {
510  rlm_sql_postgres_conn_t *conn = query_ctx->handle->conn;
511 
512  return conn->affected_rows;
513 }
514 
515 static size_t sql_escape_func(request_t *request, char *out, size_t outlen, char const *in, void *arg)
516 {
517  size_t inlen, ret;
518  rlm_sql_handle_t *handle = talloc_get_type_abort(arg, rlm_sql_handle_t);
519  rlm_sql_postgres_conn_t *conn = handle->conn;
520  int err;
521 
522  /* Check for potential buffer overflow */
523  inlen = strlen(in);
524  if ((inlen * 2 + 1) > outlen) return 0;
525  /* Prevent integer overflow */
526  if ((inlen * 2 + 1) <= inlen) return 0;
527 
528  ret = PQescapeStringConn(conn->db, out, in, inlen, &err);
529  if (err) {
530  ROPTIONAL(REDEBUG, ERROR, "Error escaping string \"%s\": %s", in, PQerrorMessage(conn->db));
531  return 0;
532  }
533 
534  return ret;
535 }
536 
537 static int mod_instantiate(module_inst_ctx_t const *mctx)
538 {
539  rlm_sql_t const *parent = talloc_get_type_abort(mctx->mi->parent->data, rlm_sql_t);
540  rlm_sql_config_t const *config = &parent->config;
541  rlm_sql_postgresql_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_sql_postgresql_t);
542  char application_name[NAMEDATALEN];
543  char *db_string;
544 
545  /*
546  * Allow the user to set their own, or disable it
547  */
548  if (inst->send_application_name) {
549  CONF_SECTION *cs;
550  char const *name;
551 
552  cs = cf_item_to_section(cf_parent(mctx->mi->conf));
553 
554  name = cf_section_name2(cs);
555  if (!name) name = cf_section_name1(cs);
556 
557  snprintf(application_name, sizeof(application_name),
558  "FreeRADIUS " RADIUSD_VERSION_STRING " - %s (%s)", main_config->name, name);
559  }
560 
561  /*
562  * Old style database name
563  *
564  * Append options if they were set in the config
565  */
566  if (!strchr(config->sql_db, '=')) {
567  db_string = talloc_typed_asprintf(inst, "dbname='%s'", config->sql_db);
568 
569  if (config->sql_server[0] != '\0') {
570  db_string = talloc_asprintf_append(db_string, " host='%s'", config->sql_server);
571  }
572 
573  if (config->sql_port) {
574  db_string = talloc_asprintf_append(db_string, " port=%i", config->sql_port);
575  }
576 
577  if (config->sql_login[0] != '\0') {
578  db_string = talloc_asprintf_append(db_string, " user='%s'", config->sql_login);
579  }
580 
581  if (config->sql_password[0] != '\0') {
582  db_string = talloc_asprintf_append(db_string, " password='%s'", config->sql_password);
583  }
584 
585  if (fr_time_delta_ispos(config->query_timeout)) {
586  db_string = talloc_asprintf_append(db_string, " connect_timeout=%d", (int) fr_time_delta_to_sec(config->query_timeout));
587  }
588 
589  if (inst->send_application_name) {
590  db_string = talloc_asprintf_append(db_string, " application_name='%s'", application_name);
591  }
592 
593  /*
594  * New style parameter string
595  *
596  * Only append options when not already present
597  */
598  } else {
599  db_string = talloc_typed_strdup(inst, config->sql_db);
600 
601  if ((config->sql_server[0] != '\0') && !strstr(db_string, "host=")) {
602  db_string = talloc_asprintf_append(db_string, " host='%s'", config->sql_server);
603  }
604 
605  if (config->sql_port && !strstr(db_string, "port=")) {
606  db_string = talloc_asprintf_append(db_string, " port=%i", config->sql_port);
607  }
608 
609  if ((config->sql_login[0] != '\0') && !strstr(db_string, "user=")) {
610  db_string = talloc_asprintf_append(db_string, " user='%s'", config->sql_login);
611  }
612 
613  if ((config->sql_password[0] != '\0') && !strstr(db_string, "password=")) {
614  db_string = talloc_asprintf_append(db_string, " password='%s'", config->sql_password);
615  }
616 
617  if (fr_time_delta_ispos(config->query_timeout) && !strstr(db_string, "connect_timeout=")) {
618  db_string = talloc_asprintf_append(db_string, " connect_timeout=%d", (int) fr_time_delta_to_sec(config->query_timeout));
619  }
620 
621  if (inst->send_application_name && !strstr(db_string, "application_name=")) {
622  db_string = talloc_asprintf_append(db_string, " application_name='%s'", application_name);
623  }
624  }
625  inst->db_string = db_string;
626 
627  inst->states = sql_state_trie_alloc(inst);
628 
629  /*
630  * Load in the PostgreSQL specific sqlstates
631  */
632  if (sql_state_entries_from_table(inst->states, sql_state_table) < 0) return -1;
633 
634  /*
635  * Load in overrides from the driver's configuration section
636  */
637  {
638  CONF_SECTION *cs;
639 
640  cs = cf_section_find(mctx->mi->conf, "states", NULL);
641  if (cs && (sql_state_entries_from_cs(inst->states, cs) < 0)) return -1;
642  }
643 
644  return 0;
645 }
646 
647 static int mod_load(void)
648 {
649 #if defined(WITH_TLS) && (defined(HAVE_PQINITOPENSSL) || defined(HAVE_PQINITSSL))
650 # ifdef HAVE_PQINITOPENSSL
651  PQinitOpenSSL(0, 0);
652 # else
653  PQinitSSL(0);
654 # endif
655 #endif
656  return 0;
657 }
658 
659 /* Exported to rlm_sql */
662  .common = {
663  .magic = MODULE_MAGIC_INIT,
664  .name = "sql_postgresql",
665  .inst_size = sizeof(rlm_sql_postgresql_t),
666  .onload = mod_load,
669  },
671  .sql_socket_init = sql_socket_init,
672  .sql_query = sql_query,
673  .sql_select_query = sql_query,
674  .sql_fields = sql_fields,
675  .sql_fetch_row = sql_fetch_row,
676  .sql_error = sql_error,
677  .sql_finish_query = sql_free_result,
678  .sql_finish_select_query = sql_free_result,
679  .sql_affected_rows = sql_affected_rows,
680  .sql_escape_func = sql_escape_func
681 };
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
#define RCSID(id)
Definition: build.h:446
#define UNUSED
Definition: build.h:313
#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
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
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
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1187
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition: cf_util.c:684
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1173
#define cf_parent(_cf)
Definition: cf_util.h:101
#define RADIUSD_VERSION_STRING
Definition: dependency.h:39
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
static int sockfd
Definition: dhcpclient.c:56
static fr_time_delta_t timeout
Definition: dhcpclient.c:54
static fr_slen_t err
Definition: dict.h:645
static fr_slen_t in
Definition: dict.h:645
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:63
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
Definition: log.h:528
@ L_ERR
Error message.
Definition: log.h:56
main_config_t const * main_config
Main server configuration.
Definition: main_config.c:69
char const * name
Name of the daemon, usually 'radiusd'.
Definition: main_config.h:52
module_instance_t * mi
Instance of the module being instantiated.
Definition: module_ctx.h:51
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:50
static const conf_parser_t config[]
Definition: base.c:188
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define DEBUG2(fmt,...)
Definition: radclient.h:43
#define WARN(fmt,...)
Definition: radclient.h:47
#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 char const * name
static int instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_rest.c:1329
Prototypes and functions for the SQL module.
rlm_sql_t const * inst
The rlm_sql instance this connection belongs to.
Definition: rlm_sql.h:115
int sql_state_entries_from_table(fr_trie_t *states, sql_state_entry_t const table[])
Insert the contents of a state table into the state trie.
Definition: sql_state.c:124
sql_rcode_t rcode
What should happen if we receive this error.
Definition: rlm_sql.h:70
void * conn
Database specific connection handle.
Definition: rlm_sql.h:114
char const * meaning
Verbose description.
Definition: rlm_sql.h:69
fr_table_num_sorted_t const sql_rcode_table[]
Definition: sql.c:55
fr_trie_t * sql_state_trie_alloc(TALLOC_CTX *ctx)
Allocate a sql_state trie, and insert the initial set of entries.
Definition: sql_state.c:102
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_QUERY_INVALID
Query syntax error.
Definition: rlm_sql.h:45
@ 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
fr_time_delta_t query_timeout
How long to allow queries to run for.
Definition: rlm_sql.h:94
rlm_sql_handle_t * handle
Connection handle this query is being run on.
Definition: rlm_sql.h:139
char const * sql_state
2-5 char error code.
Definition: rlm_sql.h:68
#define RLM_SQL_RCODE_FLAGS_ALT_QUERY
Can distinguish between other errors and those.
Definition: rlm_sql.h:170
sql_state_entry_t const * sql_state_entry_find(fr_trie_t const *states, char const *sql_state)
Lookup an SQL state based on an error code returned from the SQL server or client library.
Definition: sql_state.c:203
rlm_sql_row_t row
Row data from the last query.
Definition: rlm_sql.h:147
int sql_state_entries_from_cs(fr_trie_t *states, CONF_SECTION *overrides)
Insert the contents of a CONF_SECTION into the state trie.
Definition: sql_state.c:153
sql_rcode_t rcode
Result code.
Definition: rlm_sql.h:146
Definition: rlm_sql.h:61
Definition: rlm_sql.h:67
static sql_rcode_t sql_classify_error(UNUSED PGresult const *result)
static int mod_load(void)
static sql_rcode_t sql_fields(char const **out[], fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
static size_t sql_escape_func(request_t *request, char *out, size_t outlen, char const *in, void *arg)
static sql_state_entry_t sql_state_table[]
These are PostgreSQL specific error codes which are not covered in SQL 2011.
rlm_sql_driver_t rlm_sql_postgresql
static int sql_socket_init(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config, UNUSED fr_time_delta_t timeout)
static int _sql_socket_destructor(rlm_sql_postgres_conn_t *conn)
static conf_parser_t driver_config[]
static unlang_action_t sql_fetch_row(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
#define NAMEDATALEN
fr_trie_t * states
sql state trie.
static sql_rcode_t sql_free_result(fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
static int sql_affected_rows(fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
static int affected_rows(PGresult *result)
Return the number of affected rows of the result as an int instead of the string that postgresql prov...
char const * db_string
Text based configuration string.
static int mod_instantiate(module_inst_ctx_t const *mctx)
bool send_application_name
Whether we send the application name to PostgreSQL.
static unlang_action_t sql_query(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
static size_t sql_error(TALLOC_CTX *ctx, sql_log_entry_t out[], size_t outlen, fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
Retrieves any errors associated with the query context.
static void free_result_row(rlm_sql_postgres_conn_t *conn)
Free the row of the current result that's stored in the conn struct.
PostgreSQL configuration.
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
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:689
RETURN_MODULE_FAIL
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition: state_test.c:8
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:34
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
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: syserror.c:243
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition: table.h:253
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition: talloc.c:445
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition: talloc.c:492
static const char * names[8]
Definition: time.c:617
#define fr_time_delta_wrap(_time)
Definition: time.h:152
#define fr_time_delta_ispos(_a)
Definition: time.h:290
#define fr_time_delta_to_timeval(_delta)
Convert a delta to a timeval.
Definition: time.h:656
static int64_t fr_time_delta_to_sec(fr_time_delta_t delta)
Definition: time.h:647
static fr_time_delta_t fr_time_delta_sub(fr_time_delta_t a, fr_time_delta_t b)
Definition: time.h:261
#define fr_time_delta_gteq(_a, _b)
Definition: time.h:284
#define fr_time_sub(_a, _b)
Subtract one time from another.
Definition: time.h:229
A time delta, a difference in time measured in nanoseconds.
Definition: time.h:80
"server local" time.
Definition: time.h:69
static fr_slen_t parent
Definition: pair.h:844
static size_t char fr_sbuff_t size_t inlen
Definition: value.h:984
int nonnull(2, 5))
static size_t char ** out
Definition: value.h:984