The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
sql.c
Go to the documentation of this file.
1 /*
2  * sql.c rlm_sql - FreeRADIUS SQL Module
3  * Main code directly taken from ICRADIUS
4  *
5  * Version: $Id: c31ea652034c7c5d82b1bd9c6cb5597d63bd6a76 $
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  * @copyright 2001,2006 The FreeRADIUS server project
22  * @copyright 2000 Mike Machado (mike@innercite.com)
23  * @copyright 2000 Alan DeKok (aland@freeradius.org)
24  * @copyright 2001 Chad Miller (cmiller@surfsouth.com)
25  */
26 
27 RCSID("$Id: c31ea652034c7c5d82b1bd9c6cb5597d63bd6a76 $")
28 
29 #define LOG_PREFIX inst->name
30 
31 #include <freeradius-devel/server/base.h>
32 #include <freeradius-devel/util/debug.h>
33 
34 #include <sys/file.h>
35 #include <sys/stat.h>
36 
37 #include <ctype.h>
38 
39 #include "rlm_sql.h"
40 
41 /*
42  * Translate rlm_sql rcodes to humanly
43  * readable reason strings.
44  */
46  { L("need alt query"), RLM_SQL_ALT_QUERY },
47  { L("no connection"), RLM_SQL_RECONNECT },
48  { L("no more rows"), RLM_SQL_NO_MORE_ROWS },
49  { L("query invalid"), RLM_SQL_QUERY_INVALID },
50  { L("server error"), RLM_SQL_ERROR },
51  { L("success"), RLM_SQL_OK }
52 };
54 
56  { L("alternate"), RLM_SQL_ALT_QUERY },
57  { L("empty"), RLM_SQL_NO_MORE_ROWS },
58  { L("error"), RLM_SQL_ERROR },
59  { L("invalid"), RLM_SQL_QUERY_INVALID },
60  { L("ok"), RLM_SQL_OK },
61  { L("reconnect"), RLM_SQL_RECONNECT }
62 };
64 
65 void *sql_mod_conn_create(TALLOC_CTX *ctx, void *instance, fr_time_delta_t timeout)
66 {
67  int rcode;
68  rlm_sql_t *inst = talloc_get_type_abort(instance, rlm_sql_t);
69  rlm_sql_handle_t *handle;
70 
71  /*
72  * Connections cannot be alloced from the inst or
73  * pool contexts due to threading issues.
74  */
75  handle = talloc_zero(ctx, rlm_sql_handle_t);
76  if (!handle) return NULL;
77 
78  handle->log_ctx = talloc_pool(handle, 2048);
79  if (!handle->log_ctx) {
80  talloc_free(handle);
81  return NULL;
82  }
83 
84  /*
85  * Handle requires a pointer to the SQL inst so the
86  * destructor has access to the module configuration.
87  */
88  handle->inst = inst;
89 
90  rcode = (inst->driver->sql_socket_init)(handle, &inst->config, timeout);
91  if (rcode != 0) {
92  fail:
93  /*
94  * Destroy any half opened connections.
95  */
96  talloc_free(handle);
97  return NULL;
98  }
99 
100  if (inst->config.connect_query) {
101  if (rlm_sql_select_query(inst, NULL, &handle, inst->config.connect_query) != RLM_SQL_OK) goto fail;
102  (inst->driver->sql_finish_select_query)(handle, &inst->config);
103  }
104 
105  return handle;
106 }
107 
108 #if 0
109 /*************************************************************************
110  *
111  * Function: sql_pair_afrom_row
112  *
113  * Purpose: Convert one rlm_sql_row_t to a fr_pair_t, and add it to "out"
114  *
115  *************************************************************************/
116 static int sql_pair_afrom_row(TALLOC_CTX *ctx, request_t *request, fr_pair_list_t *out, rlm_sql_row_t row, fr_pair_t **relative_vp)
117 {
118  fr_pair_t *vp;
119  char const *ptr, *value;
120  char buf[FR_MAX_STRING_LEN];
121  fr_dict_attr_t const *da;
122  fr_token_t token, op = T_EOL;
123  fr_pair_list_t *my_list;
124  TALLOC_CTX *my_ctx;
125 
126  /*
127  * Verify the 'Attribute' field
128  */
129  if (!row[2] || row[2][0] == '\0') {
130  REDEBUG("Attribute field is empty or NULL, skipping the entire row");
131  return -1;
132  }
133 
134  /*
135  * Verify the 'op' field
136  */
137  if (row[4] != NULL && row[4][0] != '\0') {
138  ptr = row[4];
139  op = gettoken(&ptr, buf, sizeof(buf), false);
140  if (!fr_assignment_op[op] && !fr_comparison_op[op]) {
141  REDEBUG("Invalid op \"%s\" for attribute %s", row[4], row[2]);
142  return -1;
143  }
144 
145  } else {
146  /*
147  * Complain about empty or invalid 'op' field
148  */
149  op = T_OP_CMP_EQ;
150  REDEBUG("The op field for attribute '%s = %s' is NULL, or non-existent.", row[2], row[3]);
151  REDEBUG("You MUST FIX THIS if you want the configuration to behave as you expect");
152  }
153 
154  /*
155  * The 'Value' field may be empty or NULL
156  */
157  if (!row[3]) {
158  REDEBUG("Value field is empty or NULL, skipping the entire row");
159  return -1;
160  }
161 
162  RDEBUG3("Found row[%s]: %s %s %s", row[0], row[2], fr_table_str_by_value(fr_tokens_table, op, "<INVALID>"), row[3]);
163 
164  value = row[3];
165 
166  /*
167  * If we have a string, where the *entire* string is
168  * quoted, do xlat's.
169  */
170  if (row[3] != NULL &&
171  ((row[3][0] == '\'') || (row[3][0] == '`') || (row[3][0] == '"')) &&
172  (row[3][0] == row[3][strlen(row[3])-1])) {
173 
174  token = gettoken(&value, buf, sizeof(buf), false);
175  switch (token) {
176  /*
177  * Take the unquoted string.
178  */
182  value = buf;
183  break;
184 
185  /*
186  * Keep the original string.
187  */
188  default:
189  value = row[3];
190  break;
191  }
192  }
193 
194  /*
195  * Check for relative attributes
196  *
197  * @todo - allow "..foo" to mean "grandparent of
198  * relative_vp", and it should also update relative_vp
199  * with the new parent. However, doing this means
200  * walking the list of the current relative_vp, finding
201  * the dlist head, and then converting that into a
202  * fr_pair_t pointer. That's complex, so we don't do it
203  * right now.
204  */
205  if (row[2][0] == '.') {
206  char const *p = row[2];
207 
208  if (!*relative_vp) {
209  REDEBUG("Relative attribute '%s' can only be used immediately after an attribute of type 'group'", row[2]);
210  return -1;
211  }
212 
213  da = fr_dict_attr_by_oid(NULL, (*relative_vp)->da, p + 1);
214  if (!da) goto unknown;
215 
216  my_list = &(*relative_vp)->vp_group;
217  my_ctx = *relative_vp;
218 
219  MEM(vp = fr_pair_afrom_da(my_ctx, da));
220  fr_pair_append(my_list, vp);
221  } else {
222  /*
223  * Search in our local dictionary
224  * falling back to internal.
225  */
226  da = fr_dict_attr_by_oid(NULL, fr_dict_root(request->dict), row[2]);
227  if (!da) {
228  da = fr_dict_attr_by_oid(NULL, fr_dict_root(fr_dict_internal()), row[2]);
229  if (!da) {
230  unknown:
231  RPEDEBUG("Unknown attribute '%s'", row[2]);
232  return -1;
233  }
234  }
235 
236  my_list = out;
237  my_ctx = ctx;
238 
239  MEM(vp = fr_pair_afrom_da_nested(my_ctx, my_list, da));
240  }
241 
242  vp->op = op;
243 
244  if ((vp->vp_type == FR_TYPE_TLV) && !*value) {
245  /*
246  * Allow empty values for TLVs: we just create the value.
247  *
248  * fr_pair_value_from_str() is not yet updated to
249  * handle TLVs. Until such time as we know what
250  * to do there, we will just do a hack here,
251  * specific to the SQL module.
252  */
253  } else {
254  if (fr_pair_value_from_str(vp, value, strlen(value), NULL, true) < 0) {
255  RPEDEBUG("Error parsing value");
256  return -1;
257  }
258  }
259 
260  /*
261  * Update the relative vp.
262  */
263  if (my_list == out) switch (da->type) {
264  case FR_TYPE_STRUCTURAL:
265  *relative_vp = vp;
266  break;
267 
268  default:
269  break;
270  }
271 
272  /*
273  * If there's a relative VP, and it's not the one
274  * we just added above, and we're not adding this
275  * VP to the relative one, then nuke the relative
276  * VP.
277  */
278  if (*relative_vp && (vp != *relative_vp) && (my_ctx != *relative_vp)) {
279  *relative_vp = NULL;
280  }
281 
282  return 0;
283 }
284 #endif
285 
286 /** Call the driver's sql_fetch_row function
287  *
288  * Calls the driver's sql_fetch_row logging any errors. On success, will
289  * write row data to ``(*handle)->row``.
290  *
291  * @param out Where to write row data.
292  * @param inst Instance of #rlm_sql_t.
293  * @param request The Current request, may be NULL.
294  * @param handle Handle to retrieve errors for.
295  * @return
296  * - #RLM_SQL_OK on success.
297  * - other #sql_rcode_t constants on error.
298  */
300 {
301  sql_rcode_t ret;
302 
303  if (!*handle || !(*handle)->conn) return RLM_SQL_ERROR;
304 
305  /*
306  * We can't implement reconnect logic here, because the caller
307  * may require the original connection to free up queries or
308  * result sets associated with that connection.
309  */
310  ret = (inst->driver->sql_fetch_row)(out, *handle, &inst->config);
311  switch (ret) {
312  case RLM_SQL_OK:
313  fr_assert(*out != NULL);
314  return ret;
315 
317  fr_assert(*out == NULL);
318  return ret;
319 
320  default:
321  ROPTIONAL(RERROR, ERROR, "Error fetching row");
322  rlm_sql_print_error(inst, request, *handle, false);
323  return ret;
324  }
325 }
326 
327 /** Retrieve any errors from the SQL driver
328  *
329  * Retrieves errors from the driver from the last operation and writes them to
330  * to request/global log, in the ERROR, WARN, INFO and DEBUG categories.
331  *
332  * @param inst Instance of rlm_sql.
333  * @param request Current request, may be NULL.
334  * @param handle Handle to retrieve errors for.
335  * @param force_debug Force all errors to be logged as debug messages.
336  */
337 void rlm_sql_print_error(rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t *handle, bool force_debug)
338 {
339  char const *driver = inst->driver_submodule->name;
340  sql_log_entry_t log[20];
341  size_t num, i;
342 
343  num = (inst->driver->sql_error)(handle->log_ctx, log, (NUM_ELEMENTS(log)), handle, &inst->config);
344  if (num == 0) {
345  ROPTIONAL(RERROR, ERROR, "Unknown error");
346  return;
347  }
348 
349  for (i = 0; i < num; i++) {
350  if (force_debug) goto debug;
351 
352  switch (log[i].type) {
353  case L_ERR:
354  ROPTIONAL(RERROR, ERROR, "%s: %s", driver, log[i].msg);
355  break;
356 
357  case L_WARN:
358  ROPTIONAL(RWARN, WARN, "%s: %s", driver, log[i].msg);
359  break;
360 
361  case L_INFO:
362  ROPTIONAL(RINFO, INFO, "%s: %s", driver, log[i].msg);
363  break;
364 
365  case L_DBG:
366  default:
367  debug:
368  ROPTIONAL(RDEBUG2, DEBUG2, "%s: %s", driver, log[i].msg);
369  break;
370  }
371  }
372 
373  talloc_free_children(handle->log_ctx);
374 }
375 
376 /** Call the driver's sql_query method, reconnecting if necessary.
377  *
378  * @note Caller must call ``(inst->driver->sql_finish_query)(handle, &inst->config);``
379  * after they're done with the result.
380  *
381  * @param handle to query the database with. *handle should not be NULL, as this indicates
382  * previous reconnection attempt has failed.
383  * @param request Current request.
384  * @param inst #rlm_sql_t instance data.
385  * @param query to execute. Should not be zero length.
386  * @return
387  * - #RLM_SQL_OK on success.
388  * - #RLM_SQL_RECONNECT if a new handle is required (also sets *handle = NULL).
389  * - #RLM_SQL_QUERY_INVALID, #RLM_SQL_ERROR on invalid query or connection error.
390  * - #RLM_SQL_ALT_QUERY on constraints violation.
391  */
392 sql_rcode_t rlm_sql_query(rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t **handle, char const *query)
393 {
394  int ret = RLM_SQL_ERROR;
395  int i, count;
396 
397  /* Caller should check they have a valid handle */
398  fr_assert(*handle);
399 
400  /* There's no query to run, return an error */
401  if (query[0] == '\0') {
402  if (request) REDEBUG("Zero length query");
403  return RLM_SQL_QUERY_INVALID;
404  }
405 
406  /*
407  * inst->pool may be NULL is this function is called by sql_mod_conn_create.
408  */
409  count = inst->pool ? fr_pool_state(inst->pool)->num : 0;
410 
411  /*
412  * Here we try with each of the existing connections, then try to create
413  * a new connection, then give up.
414  */
415  for (i = 0; i < (count + 1); i++) {
416  ROPTIONAL(RDEBUG2, DEBUG2, "Executing query: %s", query);
417 
418  ret = (inst->driver->sql_query)(*handle, &inst->config, query);
419  switch (ret) {
420  case RLM_SQL_OK:
421  break;
422 
423  /*
424  * Run through all available sockets until we exhaust all existing
425  * sockets in the pool and fail to establish a *new* connection.
426  */
427  case RLM_SQL_RECONNECT:
428  *handle = fr_pool_connection_reconnect(inst->pool, request, *handle);
429  /* Reconnection failed */
430  if (!*handle) return RLM_SQL_RECONNECT;
431  /* Reconnection succeeded, try again with the new handle */
432  continue;
433 
434  /*
435  * These are bad and should make rlm_sql return invalid
436  */
438  rlm_sql_print_error(inst, request, *handle, false);
439  (inst->driver->sql_finish_query)(*handle, &inst->config);
440  break;
441 
442  /*
443  * Server or client errors.
444  *
445  * If the driver claims to be able to distinguish between
446  * duplicate row errors and other errors, and we hit a
447  * general error treat it as a failure.
448  *
449  * Otherwise rewrite it to RLM_SQL_ALT_QUERY.
450  */
451  case RLM_SQL_ERROR:
452  if (inst->driver->flags & RLM_SQL_RCODE_FLAGS_ALT_QUERY) {
453  rlm_sql_print_error(inst, request, *handle, false);
454  (inst->driver->sql_finish_query)(*handle, &inst->config);
455  break;
456  }
457  ret = RLM_SQL_ALT_QUERY;
458  FALL_THROUGH;
459 
460  /*
461  * Driver suggested using an alternative query
462  */
463  case RLM_SQL_ALT_QUERY:
464  rlm_sql_print_error(inst, request, *handle, true);
465  (inst->driver->sql_finish_query)(*handle, &inst->config);
466  break;
467 
468  }
469 
470  return ret;
471  }
472 
473  ROPTIONAL(RERROR, ERROR, "Hit reconnection limit");
474 
475  return RLM_SQL_ERROR;
476 }
477 
478 /** Call the driver's sql_select_query method, reconnecting if necessary.
479  *
480  * @note Caller must call ``(inst->driver->sql_finish_select_query)(handle, &inst->config);``
481  * after they're done with the result.
482  *
483  * @param inst #rlm_sql_t instance data.
484  * @param request Current request.
485  * @param handle to query the database with. *handle should not be NULL, as this indicates
486  * previous reconnection attempt has failed.
487  * @param query to execute. Should not be zero length.
488  * @return
489  * - #RLM_SQL_OK on success.
490  * - #RLM_SQL_RECONNECT if a new handle is required (also sets *handle = NULL).
491  * - #RLM_SQL_QUERY_INVALID, #RLM_SQL_ERROR on invalid query or connection error.
492  */
493 sql_rcode_t rlm_sql_select_query(rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t **handle, char const *query)
494 {
495  int ret = RLM_SQL_ERROR;
496  int i, count;
497 
498  /* Caller should check they have a valid handle */
499  fr_assert(*handle);
500 
501  /* There's no query to run, return an error */
502  if (query[0] == '\0') {
503  if (request) REDEBUG("Zero length query");
504 
505  return RLM_SQL_QUERY_INVALID;
506  }
507 
508  /*
509  * inst->pool may be NULL is this function is called by sql_mod_conn_create.
510  */
511  count = inst->pool ? fr_pool_state(inst->pool)->num : 0;
512 
513  /*
514  * For sanity, for when no connections are viable, and we can't make a new one
515  */
516  for (i = 0; i < (count + 1); i++) {
517  ROPTIONAL(RDEBUG2, DEBUG2, "Executing select query: %s", query);
518 
519  ret = (inst->driver->sql_select_query)(*handle, &inst->config, query);
520  switch (ret) {
521  case RLM_SQL_OK:
522  break;
523 
524  /*
525  * Run through all available sockets until we exhaust all existing
526  * sockets in the pool and fail to establish a *new* connection.
527  */
528  case RLM_SQL_RECONNECT:
529  *handle = fr_pool_connection_reconnect(inst->pool, request, *handle);
530  /* Reconnection failed */
531  if (!*handle) return RLM_SQL_RECONNECT;
532  /* Reconnection succeeded, try again with the new handle */
533  continue;
534 
536  case RLM_SQL_ERROR:
537  default:
538  rlm_sql_print_error(inst, request, *handle, false);
539  (inst->driver->sql_finish_select_query)(*handle, &inst->config);
540  break;
541  }
542 
543  return ret;
544  }
545 
546  ROPTIONAL(RERROR, ERROR, "Hit reconnection limit");
547 
548  return RLM_SQL_ERROR;
549 }
550 
551 
552 /*************************************************************************
553  *
554  * Function: sql_getvpdata
555  *
556  * Purpose: Get any group check or reply pairs
557  *
558  *************************************************************************/
559 int sql_get_map_list(TALLOC_CTX *ctx, rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t **handle,
560  map_list_t *out, char const *query, fr_dict_attr_t const *list)
561 {
562  rlm_sql_row_t row;
563  int rows = 0;
564  sql_rcode_t rcode;
565  map_t *parent = NULL;
566  tmpl_rules_t lhs_rules = (tmpl_rules_t) {
567  .attr = {
568  .dict_def = request->dict,
569  .prefix = TMPL_ATTR_REF_PREFIX_AUTO,
570  .list_def = list,
571  .list_presence = TMPL_ATTR_LIST_ALLOW,
572 
573  /*
574  * Otherwise the tmpl code returns 0 when asked
575  * to parse unknown names. So we say "please
576  * parse unknown names as unresolved attributes",
577  * and then do a second pass to complain that the
578  * thing isn't known.
579  */
580  .allow_unresolved = false
581  }
582  };
583  tmpl_rules_t rhs_rules = lhs_rules;
584 
586  rhs_rules.attr.list_def = request_attr_request;
587 
588  fr_assert(request);
589 
590  rcode = rlm_sql_select_query(inst, request, handle, query);
591  if (rcode != RLM_SQL_OK) return -1; /* error handled by rlm_sql_select_query */
592 
593  while (rlm_sql_fetch_row(&row, inst, request, handle) == RLM_SQL_OK) {
594  map_t *map;
595 
596  if (map_afrom_fields(ctx, &map, &parent, request, row[2], row[4], row[3], &lhs_rules, &rhs_rules) < 0) {
597  RPEDEBUG("Error parsing user data from database result");
598  (inst->driver->sql_finish_select_query)(*handle, &inst->config);
599  return -1;
600  }
601  if (!map->parent) map_list_insert_tail(out, map);
602 
603  rows++;
604  }
605  (inst->driver->sql_finish_select_query)(*handle, &inst->config);
606 
607  return rows;
608 }
609 
610 /*
611  * Log the query to a file.
612  */
613 void rlm_sql_query_log(rlm_sql_t const *inst, char const *filename, char const *query)
614 {
615  int fd;
616  size_t len;
617  bool failed = false; /* Write the log message outside of the critical region */
618 
619  fd = exfile_open(inst->ef, filename, 0640, NULL);
620  if (fd < 0) {
621  ERROR("Couldn't open logfile '%s': %s", filename, fr_syserror(errno));
622 
623  /* coverity[missing_unlock] */
624  return;
625  }
626 
627  len = strlen(query);
628  if ((write(fd, query, len) < 0) || (write(fd, ";\n", 2) < 0)) failed = true;
629 
630  if (failed) ERROR("Failed writing to logfile '%s': %s", filename, fr_syserror(errno));
631 
632  exfile_close(inst->ef, fd);
633 }
log_entry msg
Definition: acutest.h:794
#define RCSID(id)
Definition: build.h:444
#define L(_str)
Helper for initialising arrays of string literals.
Definition: build.h:207
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition: build.h:320
#define NUM_ELEMENTS(_t)
Definition: build.h:335
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
static fr_time_delta_t timeout
Definition: dhcpclient.c:54
fr_dict_attr_t const * fr_dict_attr_by_oid(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *oid))
Resolve an attribute using an OID string.
Definition: dict_util.c:1970
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition: dict_util.c:1997
fr_dict_t const * fr_dict_internal(void)
Definition: dict_util.c:4204
Test enumeration values.
Definition: dict_test.h:92
int exfile_open(exfile_t *ef, char const *filename, mode_t permissions, off_t *offset)
Open a new log file, or maybe an existing one.
Definition: exfile.c:505
int exfile_close(exfile_t *ef, int fd)
Close the log file.
Definition: exfile.c:561
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
Definition: log.h:528
#define RDEBUG3(fmt,...)
Definition: log.h:343
#define RWARN(fmt,...)
Definition: log.h:297
#define RERROR(fmt,...)
Definition: log.h:298
#define RINFO(fmt,...)
Definition: log.h:296
#define RPEDEBUG(fmt,...)
Definition: log.h:376
int map_afrom_fields(TALLOC_CTX *ctx, map_t **out, map_t **parent_p, request_t *request, char const *lhs, char const *op_str, char const *rhs, tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules)
Convert a fr_pair_t into a map.
Definition: map.c:2441
talloc_free(reap)
@ L_WARN
Warning.
Definition: log.h:57
@ L_ERR
Error message.
Definition: log.h:56
@ L_INFO
Informational message.
Definition: log.h:55
@ L_DBG
Only displayed when debugging is enabled.
Definition: log.h:59
@ TMPL_ATTR_REF_PREFIX_AUTO
Attribute refs may have a '&' prefix.
Definition: merged_model.c:231
@ TMPL_ATTR_REF_PREFIX_YES
Attribute refs must have '&' prefix.
Definition: merged_model.c:229
@ FR_TYPE_TLV
Contains nested attributes.
Definition: merged_model.c:118
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition: pair.c:278
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition: pair.c:1340
fr_pair_t * fr_pair_afrom_da_nested(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_dict_attr_t const *da)
Create a pair (and all intermediate parents), and append it to the list.
Definition: pair.c:462
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, bool tainted)
Convert string value to native attribute value.
Definition: pair.c:2586
fr_pool_state_t const * fr_pool_state(fr_pool_t *pool)
Get the number of connections currently in the pool.
Definition: pool.c:1171
void * fr_pool_connection_reconnect(fr_pool_t *pool, request_t *request, void *conn)
Reconnect a suspected inviable connection.
Definition: pool.c:1498
uint32_t num
Number of connections in the pool.
Definition: pool.h:67
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
#define DEBUG2(fmt,...)
Definition: radclient.h:43
#define WARN(fmt,...)
Definition: radclient.h:47
#define INFO(fmt,...)
Definition: radict.c:54
fr_dict_attr_t const * request_attr_request
Definition: request.c:41
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
TALLOC_CTX * log_ctx
Talloc pool used to avoid allocing memory when log strings need to be copied.
Definition: rlm_sql.h:104
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_QUERY_INVALID
Query syntax error.
Definition: rlm_sql.h:43
@ RLM_SQL_ALT_QUERY
Key constraint violation, use an alternative query.
Definition: rlm_sql.h:47
@ 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
#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
Definition: rlm_sql.h:59
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition: tmpl.h:344
@ TMPL_ATTR_LIST_ALLOW
Attribute refs are allowed to have a list.
Definition: tmpl.h:274
struct tmpl_rules_s tmpl_rules_t
Definition: tmpl.h:236
Optional arguments passed to vp_tmpl functions.
Definition: tmpl.h:341
size_t sql_rcode_table_len
Definition: sql.c:63
void rlm_sql_query_log(rlm_sql_t const *inst, char const *filename, char const *query)
Definition: sql.c:613
sql_rcode_t rlm_sql_select_query(rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t **handle, char const *query)
Call the driver's sql_select_query method, reconnecting if necessary.
Definition: sql.c:493
sql_rcode_t rlm_sql_fetch_row(rlm_sql_row_t *out, rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t **handle)
Call the driver's sql_fetch_row function.
Definition: sql.c:299
int sql_get_map_list(TALLOC_CTX *ctx, rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t **handle, map_list_t *out, char const *query, fr_dict_attr_t const *list)
Definition: sql.c:559
fr_table_num_sorted_t const sql_rcode_table[]
Definition: sql.c:55
void * sql_mod_conn_create(TALLOC_CTX *ctx, void *instance, fr_time_delta_t timeout)
Definition: sql.c:65
size_t sql_rcode_description_table_len
Definition: sql.c:53
fr_table_num_sorted_t const sql_rcode_description_table[]
Definition: sql.c:45
sql_rcode_t rlm_sql_query(rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t **handle, char const *query)
Call the driver's sql_query method, reconnecting if necessary.
Definition: sql.c:392
void rlm_sql_print_error(rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t *handle, bool force_debug)
Retrieve any errors from the SQL driver.
Definition: sql.c:337
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
fr_aka_sim_id_type_t type
fr_pair_t * vp
Value pair map.
Definition: map.h:77
map_t * parent
Definition: map.h:88
fr_dict_attr_t const * list_def
Default list to use with unqualified attribute reference.
Definition: tmpl.h:307
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition: tmpl.h:285
tmpl_attr_prefix_t prefix
Whether the attribute reference requires a prefix.
Definition: tmpl.h:310
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
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
An element in a lexicographically sorted array of name to num mappings.
Definition: table.h:45
A time delta, a difference in time measured in nanoseconds.
Definition: time.h:80
const bool fr_assignment_op[T_TOKEN_LAST]
Definition: token.c:168
fr_token_t gettoken(char const **ptr, char *buf, int buflen, bool unescape)
Definition: token.c:447
fr_table_num_ordered_t const fr_tokens_table[]
Definition: token.c:33
const bool fr_comparison_op[T_TOKEN_LAST]
Definition: token.c:198
enum fr_token fr_token_t
@ T_EOL
Definition: token.h:40
@ T_SINGLE_QUOTED_STRING
Definition: token.h:122
@ T_BACK_QUOTED_STRING
Definition: token.h:123
@ T_DOUBLE_QUOTED_STRING
Definition: token.h:121
@ T_OP_CMP_EQ
Definition: token.h:106
static fr_slen_t parent
Definition: pair.h:844
#define FR_TYPE_STRUCTURAL
Definition: types.h:296
#define FR_MAX_STRING_LEN
Definition: value.h:30
static size_t char ** out
Definition: value.h:984