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: 9bfc51623bb9f7f21f7093a4b11de6ad19c619c8 $
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: 9bfc51623bb9f7f21f7093a4b11de6ad19c619c8 $")
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->dl_inst->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 
265  char const *query)
266 {
267  rlm_sql_postgres_conn_t *conn = handle->conn;
268  rlm_sql_postgresql_t *inst = talloc_get_type_abort(handle->inst->driver_submodule->dl_inst->data, rlm_sql_postgresql_t);
269  fr_time_delta_t timeout = config->query_timeout;
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  return RLM_SQL_RECONNECT;
279  }
280 
281  sockfd = PQsocket(conn->db);
282  if (sockfd < 0) {
283  ERROR("Unable to obtain socket: %s", PQerrorMessage(conn->db));
284  return RLM_SQL_RECONNECT;
285  }
286 
287  if (!PQsendQuery(conn->db, query)) {
288  ERROR("Failed to send query: %s", PQerrorMessage(conn->db));
289  return RLM_SQL_RECONNECT;
290  }
291 
292  /*
293  * We try to avoid blocking by waiting until the driver indicates that
294  * the result is ready or our timeout expires
295  */
296  start = fr_time();
297  while (PQisBusy(conn->db)) {
298  int r;
299  fd_set read_fd;
300  fr_time_delta_t elapsed = fr_time_delta_wrap(0);
301 
302  FD_ZERO(&read_fd);
303  FD_SET(sockfd, &read_fd);
304 
305  if (fr_time_delta_ispos(config->query_timeout)) {
306  elapsed = fr_time_sub(fr_time(), start);
307  if (fr_time_delta_gteq(elapsed, timeout)) goto too_long;
308  }
309 
310  r = select(sockfd + 1, &read_fd, NULL, NULL, fr_time_delta_ispos(config->query_timeout) ?
312  if (r == 0) {
313  too_long:
314  ERROR("Socket read timeout after %d seconds", (int) fr_time_delta_to_sec(config->query_timeout));
315  return RLM_SQL_RECONNECT;
316  }
317  if (r < 0) {
318  if (errno == EINTR) continue;
319  ERROR("Failed in select: %s", fr_syserror(errno));
320  return RLM_SQL_RECONNECT;
321  }
322  if (!PQconsumeInput(conn->db)) {
323  ERROR("Failed reading input: %s", PQerrorMessage(conn->db));
324  return RLM_SQL_RECONNECT;
325  }
326  }
327 
328  /*
329  * Returns a PGresult pointer or possibly a null pointer.
330  * A non-null pointer will generally be returned except in
331  * out-of-memory conditions or serious errors such as inability
332  * to send the command to the server. If a null pointer is
333  * returned, it should be treated like a PGRES_FATAL_ERROR
334  * result.
335  */
336  conn->result = PQgetResult(conn->db);
337 
338  /* Discard results for appended queries */
339  while ((tmp_result = PQgetResult(conn->db)) != NULL)
340  PQclear(tmp_result);
341 
342  /*
343  * As this error COULD be a connection error OR an out-of-memory
344  * condition return value WILL be wrong SOME of the time
345  * regardless! Pick your poison...
346  */
347  if (!conn->result) {
348  ERROR("Failed getting query result: %s", PQerrorMessage(conn->db));
349  return RLM_SQL_RECONNECT;
350  }
351 
352  status = PQresultStatus(conn->result);
353  switch (status){
354  /*
355  * Successful completion of a command returning no data.
356  */
357  case PGRES_COMMAND_OK:
358  /*
359  * Affected_rows function only returns the number of affected rows of a command
360  * returning no data...
361  */
362  conn->affected_rows = affected_rows(conn->result);
363  DEBUG2("query affected rows = %i", conn->affected_rows);
364  break;
365  /*
366  * Successful completion of a command returning data (such as a SELECT or SHOW).
367  */
368 #ifdef HAVE_PGRES_SINGLE_TUPLE
369  case PGRES_SINGLE_TUPLE:
370 #endif
371  case PGRES_TUPLES_OK:
372  conn->cur_row = 0;
373  conn->affected_rows = PQntuples(conn->result);
374  numfields = PQnfields(conn->result); /*Check row storing functions..*/
375  DEBUG2("query returned rows = %i, fields = %i", conn->affected_rows, numfields);
376  break;
377 
378 #ifdef HAVE_PGRES_COPY_BOTH
379  case PGRES_COPY_BOTH:
380 #endif
381  case PGRES_COPY_OUT:
382  case PGRES_COPY_IN:
383  DEBUG2("Data transfer started");
384  break;
385 
386  /*
387  * Weird.. this shouldn't happen.
388  */
389  case PGRES_EMPTY_QUERY:
390  case PGRES_BAD_RESPONSE: /* The server's response was not understood */
391  case PGRES_NONFATAL_ERROR:
392  case PGRES_FATAL_ERROR:
393 #ifdef HAVE_PGRES_PIPELINE_SYNC
394  case PGRES_PIPELINE_SYNC:
395  case PGRES_PIPELINE_ABORTED:
396 #endif
397  break;
398  }
399 
400  return sql_classify_error(inst, status, conn->result);
401 }
402 
403 static sql_rcode_t sql_select_query(rlm_sql_handle_t * handle, rlm_sql_config_t const *config, char const *query)
404 {
405  return sql_query(handle, config, query);
406 }
407 
408 static sql_rcode_t sql_fields(char const **out[], rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
409 {
410  rlm_sql_postgres_conn_t *conn = handle->conn;
411 
412  int fields, i;
413  char const **names;
414 
415  fields = PQnfields(conn->result);
416  if (fields <= 0) return RLM_SQL_ERROR;
417 
418  MEM(names = talloc_array(handle, char const *, fields));
419 
420  for (i = 0; i < fields; i++) names[i] = PQfname(conn->result, i);
421  *out = names;
422 
423  return RLM_SQL_OK;
424 }
425 
427 {
428 
429  int records, i, len;
430  rlm_sql_postgres_conn_t *conn = handle->conn;
431 
432  *out = NULL;
433  handle->row = NULL;
434 
435  if (conn->cur_row >= PQntuples(conn->result)) return RLM_SQL_NO_MORE_ROWS;
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  *out = handle->row = conn->row;
451 
452  return RLM_SQL_OK;
453  }
454 
455  return RLM_SQL_NO_MORE_ROWS;
456 }
457 
459 {
460  rlm_sql_postgres_conn_t *conn = handle->conn;
461 
462  conn->affected_rows = PQntuples(conn->result);
463  if (conn->result) return PQnfields(conn->result);
464 
465  return 0;
466 }
467 
469 {
470  rlm_sql_postgres_conn_t *conn = handle->conn;
471 
472  if (conn->result != NULL) {
473  PQclear(conn->result);
474  conn->result = NULL;
475  }
476 
477  free_result_row(conn);
478 
479  return 0;
480 }
481 
482 /** Retrieves any errors associated with the connection handle
483  *
484  * @note Caller will free any memory allocated in ctx.
485  *
486  * @param ctx to allocate temporary error buffers in.
487  * @param out Array of sql_log_entrys to fill.
488  * @param outlen Length of out array.
489  * @param handle rlm_sql connection handle.
490  * @param config rlm_sql config.
491  * @return number of errors written to the #sql_log_entry_t array.
492  */
493 static size_t sql_error(TALLOC_CTX *ctx, sql_log_entry_t out[], size_t outlen,
495 {
496  rlm_sql_postgres_conn_t *conn = handle->conn;
497  char const *p, *q;
498  size_t i = 0;
499 
500  fr_assert(outlen > 0);
501 
502  p = PQerrorMessage(conn->db);
503  while ((q = strchr(p, '\n'))) {
504  out[i].type = L_ERR;
505  out[i].msg = talloc_typed_asprintf(ctx, "%.*s", (int) (q - p), p);
506  p = q + 1;
507  if (++i == outlen) return outlen;
508  }
509  if (*p != '\0') {
510  out[i].type = L_ERR;
511  out[i].msg = p;
512  i++;
513  }
514 
515  return i;
516 }
517 
519 {
520  rlm_sql_postgres_conn_t *conn = handle->conn;
521 
522  return conn->affected_rows;
523 }
524 
525 static size_t sql_escape_func(request_t *request, char *out, size_t outlen, char const *in, void *arg)
526 {
527  size_t inlen, ret;
528  rlm_sql_handle_t *handle = talloc_get_type_abort(arg, rlm_sql_handle_t);
529  rlm_sql_postgres_conn_t *conn = handle->conn;
530  int err;
531 
532  /* Check for potential buffer overflow */
533  inlen = strlen(in);
534  if ((inlen * 2 + 1) > outlen) return 0;
535  /* Prevent integer overflow */
536  if ((inlen * 2 + 1) <= inlen) return 0;
537 
538  ret = PQescapeStringConn(conn->db, out, in, inlen, &err);
539  if (err) {
540  ROPTIONAL(REDEBUG, ERROR, "Error escaping string \"%s\": %s", in, PQerrorMessage(conn->db));
541  return 0;
542  }
543 
544  return ret;
545 }
546 
547 static int mod_bootstrap(module_inst_ctx_t const *mctx)
548 {
549  rlm_sql_t const *parent = talloc_get_type_abort(mctx->inst->parent->data, rlm_sql_t);
550  rlm_sql_config_t const *config = &parent->config;
551  rlm_sql_postgresql_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_sql_postgresql_t);
552  char application_name[NAMEDATALEN];
553  char *db_string;
554 
555  /*
556  * Allow the user to set their own, or disable it
557  */
558  if (inst->send_application_name) {
559  CONF_SECTION *cs;
560  char const *name;
561 
562  cs = cf_item_to_section(cf_parent(mctx->inst->conf));
563 
564  name = cf_section_name2(cs);
565  if (!name) name = cf_section_name1(cs);
566 
567  snprintf(application_name, sizeof(application_name),
568  "FreeRADIUS " RADIUSD_VERSION_STRING " - %s (%s)", main_config->name, name);
569  }
570 
571  /*
572  * Old style database name
573  *
574  * Append options if they were set in the config
575  */
576  if (!strchr(config->sql_db, '=')) {
577  db_string = talloc_typed_asprintf(inst, "dbname='%s'", config->sql_db);
578 
579  if (config->sql_server[0] != '\0') {
580  db_string = talloc_asprintf_append(db_string, " host='%s'", config->sql_server);
581  }
582 
583  if (config->sql_port) {
584  db_string = talloc_asprintf_append(db_string, " port=%i", config->sql_port);
585  }
586 
587  if (config->sql_login[0] != '\0') {
588  db_string = talloc_asprintf_append(db_string, " user='%s'", config->sql_login);
589  }
590 
591  if (config->sql_password[0] != '\0') {
592  db_string = talloc_asprintf_append(db_string, " password='%s'", config->sql_password);
593  }
594 
595  if (fr_time_delta_ispos(config->query_timeout)) {
596  db_string = talloc_asprintf_append(db_string, " connect_timeout=%d", (int) fr_time_delta_to_sec(config->query_timeout));
597  }
598 
599  if (inst->send_application_name) {
600  db_string = talloc_asprintf_append(db_string, " application_name='%s'", application_name);
601  }
602 
603  /*
604  * New style parameter string
605  *
606  * Only append options when not already present
607  */
608  } else {
609  db_string = talloc_typed_strdup(inst, config->sql_db);
610 
611  if ((config->sql_server[0] != '\0') && !strstr(db_string, "host=")) {
612  db_string = talloc_asprintf_append(db_string, " host='%s'", config->sql_server);
613  }
614 
615  if (config->sql_port && !strstr(db_string, "port=")) {
616  db_string = talloc_asprintf_append(db_string, " port=%i", config->sql_port);
617  }
618 
619  if ((config->sql_login[0] != '\0') && !strstr(db_string, "user=")) {
620  db_string = talloc_asprintf_append(db_string, " user='%s'", config->sql_login);
621  }
622 
623  if ((config->sql_password[0] != '\0') && !strstr(db_string, "password=")) {
624  db_string = talloc_asprintf_append(db_string, " password='%s'", config->sql_password);
625  }
626 
627  if (fr_time_delta_ispos(config->query_timeout) && !strstr(db_string, "connect_timeout=")) {
628  db_string = talloc_asprintf_append(db_string, " connect_timeout=%d", (int) fr_time_delta_to_sec(config->query_timeout));
629  }
630 
631  if (inst->send_application_name && !strstr(db_string, "application_name=")) {
632  db_string = talloc_asprintf_append(db_string, " application_name='%s'", application_name);
633  }
634  }
635  inst->db_string = db_string;
636 
637  inst->states = sql_state_trie_alloc(inst);
638 
639  /*
640  * Load in the PostgreSQL specific sqlstates
641  */
642  if (sql_state_entries_from_table(inst->states, sql_state_table) < 0) return -1;
643 
644  /*
645  * Load in overrides from the driver's configuration section
646  */
647  {
648  CONF_SECTION *cs;
649 
650  cs = cf_section_find(mctx->inst->conf, "states", NULL);
651  if (cs && (sql_state_entries_from_cs(inst->states, cs) < 0)) return -1;
652  }
653 
654  return 0;
655 }
656 
657 static int mod_load(void)
658 {
659 #if defined(WITH_TLS) && (defined(HAVE_PQINITOPENSSL) || defined(HAVE_PQINITSSL))
660 # ifdef HAVE_PQINITOPENSSL
661  PQinitOpenSSL(0, 0);
662 # else
663  PQinitSSL(0);
664 # endif
665 #endif
666  return 0;
667 }
668 
669 /* Exported to rlm_sql */
672  .common = {
673  .magic = MODULE_MAGIC_INIT,
674  .name = "sql_postgresql",
675  .inst_size = sizeof(rlm_sql_postgresql_t),
676  .onload = mod_load,
678  .bootstrap = mod_bootstrap
679  },
681  .number = 2,
682  .sql_socket_init = sql_socket_init,
683  .sql_query = sql_query,
684  .sql_select_query = sql_select_query,
685  .sql_num_fields = sql_num_fields,
686  .sql_fields = sql_fields,
687  .sql_fetch_row = sql_fetch_row,
688  .sql_error = sql_error,
689  .sql_finish_query = sql_free_result,
690  .sql_finish_select_query = sql_free_result,
691  .sql_affected_rows = sql_affected_rows,
692  .sql_escape_func = sql_escape_func
693 };
#define RCSID(id)
Definition: build.h:444
#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:970
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1126
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition: cf_util.c:649
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1112
#define cf_parent(_cf)
Definition: cf_util.h:98
#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
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 *_CONST parent
Parent module's instance (if any).
Definition: dl_module.h:167
#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
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 REDEBUG(fmt,...)
Definition: radclient.h:52
#define DEBUG2(fmt,...)
Definition: radclient.h:43
#define WARN(fmt,...)
Definition: radclient.h:47
static char const * name
Prototypes and functions for the SQL module.
rlm_sql_t const * inst
The rlm_sql instance this connection belongs to.
Definition: rlm_sql.h:103
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:68
void * conn
Database specific connection handle.
Definition: rlm_sql.h:101
char const * meaning
Verbose description.
Definition: rlm_sql.h:67
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
sql_rcode_t
Action to take at end of an SQL query.
Definition: rlm_sql.h:42
@ RLM_SQL_QUERY_INVALID
Query syntax error.
Definition: rlm_sql.h:43
@ 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 const * sql_state
2-5 char error code.
Definition: rlm_sql.h:66
#define RLM_SQL_RCODE_FLAGS_ALT_QUERY
Can distinguish between other errors and those.
Definition: rlm_sql.h:116
char ** rlm_sql_row_t
Definition: rlm_sql.h:57
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
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
rlm_sql_row_t row
Row data from the last query.
Definition: rlm_sql.h:102
Definition: rlm_sql.h:59
Definition: rlm_sql.h:65
static sql_rcode_t sql_classify_error(UNUSED PGresult const *result)
static int mod_load(void)
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.
static size_t sql_error(TALLOC_CTX *ctx, sql_log_entry_t out[], size_t outlen, rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
Retrieves any errors associated with the connection handle.
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 sql_rcode_t sql_fetch_row(rlm_sql_row_t *out, rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
static conf_parser_t driver_config[]
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)
#define NAMEDATALEN
fr_trie_t * states
sql state trie.
static sql_rcode_t sql_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t const *config, char const *query)
static int sql_affected_rows(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
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 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.
bool send_application_name
Whether we send the application name to PostgreSQL.
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.
static sql_rcode_t sql_fields(char const **out[], rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
PostgreSQL configuration.
dl_module_inst_t * dl_inst
Structure containing the module's instance data, configuration, and dl handle.
Definition: module.h:183
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:689
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:148
module_instance_t * driver_submodule
Driver's submodule.
Definition: rlm_sql.h:185
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:333
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition: talloc.c:380
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:288
#define fr_time_delta_to_timeval(_delta)
Convert a delta to a timeval.
Definition: time.h:654
static int64_t fr_time_delta_to_sec(fr_time_delta_t delta)
Definition: time.h:645
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:282
#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