The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_sql_sqlite.c
Go to the documentation of this file.
1/*
2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 1c1adacf775bb9a83a180c0d08a84873f0470e13 $
19 * @file rlm_sql_sqlite.c
20 * @brief SQLite driver.
21 *
22 * @copyright 2013 Network RADIUS SAS (legal@networkradius.com)
23 * @copyright 2007 Apple Inc.
24 */
25RCSID("$Id: 1c1adacf775bb9a83a180c0d08a84873f0470e13 $")
26
27#define LOG_PREFIX "sql - sqlite"
28#include <freeradius-devel/server/base.h>
29#include <freeradius-devel/util/debug.h>
30
31#include <fcntl.h>
32#include <sys/stat.h>
33
34#include <sqlite3.h>
35
36#include "rlm_sql.h"
37#include "rlm_sql_trunk.h"
38#include "config.h"
39
40#define BOOTSTRAP_MAX (1048576 * 10)
41
42/*
43 * Allow us to use versions < 3.6.0 beta0
44 */
45#ifndef SQLITE_OPEN_NOMUTEX
46# define SQLITE_OPEN_NOMUTEX 0
47#endif
48
49#ifndef HAVE_SQLITE3_INT64
50typedef sqlite_int64 sqlite3_int64;
51#endif
52
53typedef struct {
54 sqlite3 *db;
55 sqlite3_stmt *statement;
58
59typedef struct {
60 char const *filename;
63
68
69/** Convert an sqlite status code to an sql_rcode_t
70 *
71 * @param status to convert.
72 * @return
73 * - RLM_SQL_OK - If no errors found.
74 * - RLM_SQL_ERROR - If a known, non-fatal, error occurred.
75 * - RLM_SQL_ALT_QUERY - If a constraints violation occurred.
76 * - RLM_SQL_RECONNECT - Anything else, we assume the connection can no longer be used.
77 */
79{
80 /*
81 * Lowest byte is error category, other byte may contain
82 * the extended error, depending on version.
83 */
84 switch (status & 0xff) {
85 /*
86 * Not errors
87 */
88 case SQLITE_OK:
89 case SQLITE_DONE:
90 case SQLITE_ROW:
91 return RLM_SQL_OK;
92 /*
93 * User/transient errors
94 */
95 case SQLITE_ERROR: /* SQL error or missing database */
96 case SQLITE_FULL:
97 case SQLITE_MISMATCH:
98 case SQLITE_BUSY: /* Can be caused by database locking */
99 return RLM_SQL_ERROR;
100
101 /*
102 * Constraints violations
103 */
104 case SQLITE_CONSTRAINT:
105 return RLM_SQL_ALT_QUERY;
106
107 /*
108 * Errors with the handle, that probably require reinitialisation
109 */
110 default:
111 return RLM_SQL_RECONNECT;
112 }
113}
114
115/** Determine if an error occurred, and what type of error it was
116 *
117 * @param db handle to extract error from (may be NULL).
118 * @param status to check (if unused, set to SQLITE_OK).
119 * @return
120 * - RLM_SQL_OK - If no errors found.
121 * - RLM_SQL_ERROR - If a known, non-fatal, error occurred.
122 * - RLM_SQL_ALT_QUERY - If a constraints violation occurred.
123 * - RLM_SQL_RECONNECT - Anything else. We assume the connection can no longer be used.
124 */
125static sql_rcode_t sql_check_error(sqlite3 *db, int status)
126{
127 int hstatus = SQLITE_OK;
128
129 if (db) {
130 hstatus = sqlite3_errcode(db);
131 switch (hstatus & 0xff) {
132 case SQLITE_OK:
133 case SQLITE_DONE:
134 case SQLITE_ROW:
135 hstatus = SQLITE_OK;
136 break;
137
138 default:
139 break;
140 }
141 }
142
143 switch (status & 0xff) {
144 case SQLITE_OK:
145 case SQLITE_DONE:
146 case SQLITE_ROW:
147 status = SQLITE_OK;
148 break;
149
150 default:
151 break;
152 }
153
154 if (status != SQLITE_OK) return sql_error_to_rcode(status);
155 if (hstatus != SQLITE_OK) return sql_error_to_rcode(hstatus);
156
157 return RLM_SQL_OK;
158}
159
160/** Print an error to the global debug log
161 *
162 * If status does not indicate success, write an error to the global error log.
163 *
164 * @note The error code will be appended to the fmt string in the format ": code 0x<hex> (<int>)[: <string>]".
165 *
166 * @param db handle to extract error from (may be NULL).
167 * @param status to check (if unused, set to SQLITE_OK).
168 * @param fmt to prepend.
169 * @param ... arguments to fmt.
170 */
171static void sql_print_error(sqlite3 *db, int status, char const *fmt, ...)
172 CC_HINT(format (printf, 3, 4)) CC_HINT(nonnull (3));
173static void sql_print_error(sqlite3 *db, int status, char const *fmt, ...)
174{
175 va_list ap;
176 char *p;
177 int hstatus = SQLITE_OK;
178
179 if (db) {
180 hstatus = sqlite3_errcode(db);
181 switch (hstatus & 0xff) {
182 case SQLITE_OK:
183 case SQLITE_DONE:
184 case SQLITE_ROW:
185 hstatus = SQLITE_OK;
186 break;
187
188 default:
189 break;
190 }
191 }
192
193 switch (status & 0xff) {
194 case SQLITE_OK:
195 case SQLITE_DONE:
196 case SQLITE_ROW:
197 status = SQLITE_OK;
198 break;
199
200 default:
201 break;
202 }
203
204 /*
205 * No errors!
206 */
207 if ((hstatus == SQLITE_OK) && (status == SQLITE_OK)) return;
208
209 /*
210 * At least one error...
211 */
212 va_start(ap, fmt);
213 MEM(p = talloc_vasprintf(NULL, fmt, ap));
214 va_end(ap);
215
216 /*
217 * Disagreement between handle, and function return code,
218 * print them both.
219 */
220 if ((status != SQLITE_OK) && (status != hstatus)) {
221 ERROR("%s: Code 0x%04x (%i): %s", p, status, status, sqlite3_errstr(status));
222 }
223
224 if (hstatus != SQLITE_OK) ERROR("%s: Code 0x%04x (%i): %s",
225 p, hstatus, hstatus, sqlite3_errmsg(db));
226}
227
228static int sql_loadfile(TALLOC_CTX *ctx, sqlite3 *db, char const *filename)
229{
230 ssize_t len;
231 int statement_len, statement_cnt = 0;
232 char *buffer;
233 char const *p;
234 int cl;
235 FILE *f;
236 struct stat finfo;
237
238 int status;
239 sqlite3_stmt *statement;
240 char const *z_tail;
241
242 INFO("Executing SQL statements from file \"%s\"", filename);
243
244 f = fopen(filename, "r");
245 if (!f) {
246 ERROR("Failed opening SQL file \"%s\": %s", filename,
247 fr_syserror(errno));
248
249 return -1;
250 }
251
252 if (fstat(fileno(f), &finfo) < 0) {
253 ERROR("Failed stating SQL file \"%s\": %s", filename,
254 fr_syserror(errno));
255
256 fclose(f);
257
258 return -1;
259 }
260
261 if (finfo.st_size > BOOTSTRAP_MAX) {
262 too_big:
263 ERROR("Size of SQL (%zu) file exceeds limit (%uk)",
264 (size_t) finfo.st_size / 1024, BOOTSTRAP_MAX / 1024);
265
266 fclose(f);
267
268 return -1;
269 }
270
271 MEM(buffer = talloc_array(ctx, char, finfo.st_size + 1));
272 len = fread(buffer, sizeof(char), finfo.st_size, f);
273 if (len > finfo.st_size) {
275 goto too_big;
276 }
277
278 if (!len) {
279 if (ferror(f)) {
280 ERROR("Error reading SQL file: %s", fr_syserror(errno));
281
282 fclose(f);
284
285 return -1;
286 }
287
288 DEBUG("Ignoring empty SQL file");
289
290 fclose(f);
292
293 return 0;
294 }
295
296 buffer[len] = '\0';
297 fclose(f);
298
299 /*
300 * Check if input data is UTF-8. Allow CR/LF \t, too.
301 */
302 for (p = buffer; p < (buffer + len); p += cl) {
303 if (*p < ' ') {
304 if ((*p != 0x0a) && (*p != 0x0d) && (*p != '\t')) break;
305 cl = 1;
306 } else {
307 cl = fr_utf8_char((uint8_t const *) p, -1);
308 if (!cl) break;
309 }
310 }
311
312 if ((p - buffer) != len) {
313 ERROR("Bootstrap file contains non-UTF8 char at offset %zu", p - buffer);
315 return -1;
316 }
317
318 p = buffer;
319 while (*p) {
320 statement_len = len - (p - buffer);
321 status = sqlite3_prepare_v2(db, p, statement_len, &statement, &z_tail);
322
323 if (sql_check_error(db, status) != RLM_SQL_OK) {
324 sql_print_error(db, status, "Failed preparing statement %i", statement_cnt);
326 return -1;
327 }
328
329 /*
330 * No SQL statement was found
331 */
332 if (!statement) break;
333
334 status = sqlite3_step(statement);
335 if (sql_check_error(db, status) != RLM_SQL_OK) {
336 sql_print_error(db, status, "Failed executing statement %i", statement_cnt);
337 sqlite3_finalize(statement);
339 return -1;
340 }
341
342 status = sqlite3_finalize(statement);
343 if (sql_check_error(db, status) != RLM_SQL_OK) {
344 sql_print_error(db, status, "Failed finalizing statement %i", statement_cnt);
346 return -1;
347 }
348
349 statement_cnt++;
350 p = z_tail;
351 }
352
354 return 0;
355}
356
357static void _sql_greatest(sqlite3_context *ctx, int num_values, sqlite3_value **values)
358{
359 int i;
360 sqlite3_int64 value, max = 0;
361
362 for (i = 0; i < num_values; i++) {
363 value = sqlite3_value_int64(values[i]);
364 if (value > max) {
365 max = value;
366 }
367 }
368
369 sqlite3_result_int64(ctx, max);
370}
371
372CC_NO_UBSAN(function) /* UBSAN: false positive - public vs private connection_t trips --fsanitize=function*/
373static connection_state_t _sql_connection_init(void **h, connection_t *conn, void *uctx)
374{
376 rlm_sql_sqlite_t *inst = talloc_get_type_abort(sql->driver_submodule->data, rlm_sql_sqlite_t);
378 rlm_sql_config_t const *config = &sql->config;
379 int status;
380
381 MEM(c = talloc_zero(conn, rlm_sql_sqlite_conn_t));
382
383 INFO("Opening SQLite database \"%s\"", inst->filename);
384 status = sqlite3_open_v2(inst->filename, &(c->db), SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX, NULL);
385
386 if (!c->db || (sql_check_error(c->db, status) != RLM_SQL_OK)) {
387 sql_print_error(c->db, status, "Error opening SQLite database \"%s\"", inst->filename);
388 if (!inst->bootstrap) {
389 INFO("Use the sqlite driver 'bootstrap' option to automatically create the database file");
390 }
391 error:
392 talloc_free(c);
394 }
395 status = sqlite3_busy_timeout(c->db, fr_time_delta_to_sec(config->query_timeout));
396 if (sql_check_error(c->db, status) != RLM_SQL_OK) {
397 sql_print_error(c->db, status, "Error setting busy timeout");
398 goto error;
399 }
400
401 /*
402 * Enable extended return codes for extra debugging info.
403 */
404 status = sqlite3_extended_result_codes(c->db, 1);
405 if (sql_check_error(c->db, status) != RLM_SQL_OK) {
406 sql_print_error(c->db, status, "Error enabling extended result codes");
407 goto error;
408 }
409
410 status = sqlite3_create_function_v2(c->db, "GREATEST", -1, SQLITE_ANY, NULL,
411 _sql_greatest, NULL, NULL, NULL);
412 if (sql_check_error(c->db, status) != RLM_SQL_OK) {
413 sql_print_error(c->db, status, "Failed registering 'GREATEST' sql function");
414 goto error;
415 }
416
417 *h = c;
418
420}
421
422static void _sql_connection_close(UNUSED fr_event_list_t *el, void *h, UNUSED void *uctx)
423{
424 rlm_sql_sqlite_conn_t *c = talloc_get_type_abort(h, rlm_sql_sqlite_conn_t);
425 int status = 0;
426
427 DEBUG2("Socket destructor called, closing socket");
428
429 if (c->db) {
430 status = sqlite3_close(c->db);
431 if (status != SQLITE_OK) WARN("Got SQLite error when closing socket: %s",
432 sqlite3_errmsg(c->db));
433 }
434}
435
436static sql_rcode_t sql_fields(char const **out[], fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
437{
438 rlm_sql_sqlite_conn_t *conn = talloc_get_type_abort(query_ctx->tconn->conn->h, rlm_sql_sqlite_conn_t);
439
440 int fields, i;
441 char const **names;
442
443 fields = sqlite3_column_count(conn->statement);
444 if (fields <= 0) return RLM_SQL_ERROR;
445
446 MEM(names = talloc_array(query_ctx, char const *, fields));
447
448 for (i = 0; i < fields; i++) names[i] = sqlite3_column_name(conn->statement, i);
449 *out = names;
450
451 return RLM_SQL_OK;
452}
453
454static unlang_action_t sql_fetch_row(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
455{
456 fr_sql_query_t *query_ctx = talloc_get_type_abort(uctx, fr_sql_query_t);
457 int status, i = 0;
458 rlm_sql_sqlite_conn_t *conn = talloc_get_type_abort(query_ctx->tconn->conn->h, rlm_sql_sqlite_conn_t);
459 char **row;
460
461 TALLOC_FREE(query_ctx->row);
462
463 /*
464 * Executes the SQLite query and iterates over the results
465 */
466 status = sqlite3_step(conn->statement);
467
468 /*
469 * Error getting next row
470 */
471 if (sql_check_error(conn->db, status) != RLM_SQL_OK) {
472 error:
473 query_ctx->rcode = RLM_SQL_ERROR;
475 }
476
477 /*
478 * No more rows to process (we're done)
479 */
480 if (status == SQLITE_DONE) {
481 query_ctx->rcode = RLM_SQL_NO_MORE_ROWS;
483 }
484
485 /*
486 * We only need to do this once per result set, because
487 * the number of columns won't change.
488 */
489 if (conn->col_count == 0) {
490 conn->col_count = sqlite3_column_count(conn->statement);
491 if (conn->col_count == 0) goto error;
492 }
493
494 /*
495 * Free the previous result (also gets called on finish_query)
496 */
497 MEM(row = query_ctx->row = talloc_zero_array(query_ctx, char *, conn->col_count + 1));
498
499 for (i = 0; i < conn->col_count; i++) {
500 switch (sqlite3_column_type(conn->statement, i)) {
501 case SQLITE_INTEGER:
502 MEM(row[i] = talloc_typed_asprintf(row, "%d", sqlite3_column_int(conn->statement, i)));
503 break;
504
505 case SQLITE_FLOAT:
506 MEM(row[i] = talloc_typed_asprintf(row, "%f", sqlite3_column_double(conn->statement, i)));
507 break;
508
509 case SQLITE_TEXT:
510 {
511 char const *p;
512 p = (char const *) sqlite3_column_text(conn->statement, i);
513
514 if (p) MEM(row[i] = talloc_typed_strdup(row, p));
515 }
516 break;
517
518 case SQLITE_BLOB:
519 {
520 uint8_t const *p;
521 size_t len;
522
523 p = sqlite3_column_blob(conn->statement, i);
524 if (p) {
525 len = sqlite3_column_bytes(conn->statement, i);
526
527 MEM(row[i] = talloc_zero_array(row, char, len + 1));
528 memcpy(row[i], p, len);
529 }
530 }
531 break;
532
533 default:
534 break;
535 }
536 }
537
538 query_ctx->rcode = RLM_SQL_OK;
540}
541
543{
544 rlm_sql_sqlite_conn_t *conn = talloc_get_type_abort(query_ctx->tconn->conn->h, rlm_sql_sqlite_conn_t);
545
546 if (conn->statement) {
547 TALLOC_FREE(query_ctx->row);
548
549 (void) sqlite3_finalize(conn->statement);
550 conn->statement = NULL;
551 conn->col_count = 0;
552 }
553
554 /*
555 * There's no point in checking the code returned by finalize
556 * as it'll have already been encountered elsewhere in the code.
557 *
558 * It's just the last error that occurred processing the
559 * statement.
560 */
561 return RLM_SQL_OK;
562}
563
564/** Retrieves any errors associated with the query context
565 *
566 * @note Caller will free any memory allocated in ctx.
567 *
568 * @param ctx to allocate temporary error buffers in.
569 * @param out Array of sql_log_entrys to fill.
570 * @param outlen Length of out array.
571 * @param query_ctx Query context to retrieve error for.
572 * @return number of errors written to the #sql_log_entry_t array.
573 */
574static size_t sql_error(UNUSED TALLOC_CTX *ctx, sql_log_entry_t out[], NDEBUG_UNUSED size_t outlen,
575 fr_sql_query_t *query_ctx)
576{
577 rlm_sql_sqlite_conn_t *conn = talloc_get_type_abort(query_ctx->tconn->conn->h, rlm_sql_sqlite_conn_t);
578 char const *error;
579
580 fr_assert(outlen > 0);
581
582 error = sqlite3_errmsg(conn->db);
583 if (!error) return 0;
584
585 out[0].type = L_ERR;
586 out[0].msg = error;
587
588 return 1;
589}
590
592{
593 return sql_free_result(query_ctx, config);
594}
595
596static int sql_affected_rows(fr_sql_query_t *query_ctx,
598{
599 rlm_sql_sqlite_conn_t *conn = talloc_get_type_abort(query_ctx->tconn->conn->h, rlm_sql_sqlite_conn_t);
600
601 if (conn->db) return sqlite3_changes(conn->db);
602
603 return -1;
604}
605
607
608CC_NO_UBSAN(function) /* UBSAN: false positive - public vs private connection_t trips --fsanitize=function*/
610 connection_t *conn, UNUSED void *uctx)
611{
612 rlm_sql_sqlite_conn_t *sql_conn = talloc_get_type_abort(conn->h, rlm_sql_sqlite_conn_t);
613 trunk_request_t *treq;
614 request_t *request;
615 fr_sql_query_t *query_ctx;
616 int status;
617 char const *z_tail;
618
619 if (trunk_connection_pop_request(&treq, tconn) != 0) return;
620 if (!treq) return;
621
622 query_ctx = talloc_get_type_abort(treq->preq, fr_sql_query_t);
623 request = query_ctx->request;
624 query_ctx->tconn = tconn;
625
626 ROPTIONAL(RDEBUG2, DEBUG2, "Executing query: %s", query_ctx->query_str);
627 status = sqlite3_prepare_v2(sql_conn->db, query_ctx->query_str, strlen(query_ctx->query_str),
628 &sql_conn->statement, &z_tail);
629 query_ctx->rcode = sql_check_error(sql_conn->db, status);
630 if (query_ctx->rcode != RLM_SQL_OK) {
631 error:
632 query_ctx->status = SQL_QUERY_FAILED;
634 return;
635 }
636
637 if (query_ctx->type == SQL_QUERY_OTHER) {
638 status = sqlite3_step(sql_conn->statement);
639 query_ctx->rcode = sql_check_error(sql_conn->db, status);
640 if (query_ctx->rcode == RLM_SQL_ERROR) goto error;
641 }
642
644}
645
647
648static void sql_request_fail(UNUSED request_t *request, void *preq, UNUSED void *rctx,
649 UNUSED trunk_request_state_t state, UNUSED void *uctx)
650{
651 fr_sql_query_t *query_ctx = talloc_get_type_abort(preq, fr_sql_query_t);
652
653 query_ctx->treq = NULL;
654 if (query_ctx->rcode == RLM_SQL_OK) query_ctx->rcode = RLM_SQL_ERROR;
655}
656
657static void sql_request_complete(UNUSED request_t *request, void *preq, UNUSED void *rctx, UNUSED void *uctx)
658{
659 fr_sql_query_t *query_ctx = talloc_get_type_abort(preq, fr_sql_query_t);
660
661 sql_free_result(query_ctx, NULL);
662}
663
664static int mod_instantiate(module_inst_ctx_t const *mctx)
665{
666 rlm_sql_t const *parent = talloc_get_type_abort(mctx->mi->parent->data, rlm_sql_t);
667 rlm_sql_config_t const *config = &parent->config;
668 rlm_sql_sqlite_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_sql_sqlite_t);
669 bool exists;
670 struct stat buf;
671 int fd;
672 char const *r;
673
674 if (!inst->filename) {
675 MEM(inst->filename = talloc_typed_asprintf(inst, "%s/%s",
676 main_config->raddb_dir, config->sql_db));
677 }
678
679 /*
680 * We will try to create the database if it doesn't exist, up to and
681 * including creating the directory it should live in, in which case
682 * we get to call fr_dirfd() again. Hence failing this first fr_dirfd()
683 * just means the database isn't there.
684 */
685 if (fr_dirfd(&fd, &r, inst->filename) < 0) {
686 exists = false;
687 } else if (fstatat(fd, r, &buf, 0) == 0) {
688 exists = true;
689 } else if (errno == ENOENT) {
690 exists = false;
691 } else {
692 ERROR("Database exists, but couldn't be opened: %s", fr_syserror(errno));
693 close(fd);
694 return -1;
695 }
696
697 if (cf_pair_find(mctx->mi->conf, "bootstrap")) {
698 inst->bootstrap = true;
699 }
700
701 if (inst->bootstrap && !exists) {
702 int status;
703 int ret;
704 char const *p;
705 char *buff;
706 sqlite3 *db = NULL;
707 CONF_PAIR *cp;
708
709 INFO("Database \"%s\" doesn't exist, creating it and loading schema", inst->filename);
710
711 p = strrchr(inst->filename, '/');
712 if (p) {
713 size_t len = (p - inst->filename) + 1;
714
715 buff = talloc_array(mctx->mi->conf, char, len);
716 strlcpy(buff, inst->filename, len);
717 } else {
718 MEM(buff = talloc_typed_strdup(mctx->mi->conf, inst->filename));
719 }
720
721 ret = fr_mkdir(NULL, buff, -1, 0700, NULL, NULL);
723 if (ret < 0) {
724 PERROR("Failed creating directory for SQLite database");
725
726 return -1;
727 }
728 (void) fr_dirfd(&fd, &r, inst->filename);
729
730 status = sqlite3_open_v2(inst->filename, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
731 if (!db) {
732 ERROR("Failed creating opening/creating SQLite database: %s",
733 sqlite3_errstr(status));
734 goto unlink;
735 }
736
737 if (sql_check_error(db, status) != RLM_SQL_OK) {
738 (void) sqlite3_close(db);
739
740 goto unlink;
741 }
742
743 /*
744 * Execute multiple bootstrap SQL files in order
745 */
746 for (cp = cf_pair_find(mctx->mi->conf, "bootstrap");
747 cp;
748 cp = cf_pair_find_next(mctx->mi->conf, cp, "bootstrap")) {
749 p = cf_pair_value(cp);
750 if (!p) continue;
751
752 ret = sql_loadfile(mctx->mi->conf, db, p);
753 if (ret < 0) {
754 (void) sqlite3_close(db);
755 goto unlink;
756 }
757 }
758
759 status = sqlite3_close(db);
760 if (status != SQLITE_OK) {
761 /*
762 * Safer to use sqlite3_errstr here, just in case the handle is in a weird state
763 */
764 ERROR("Error closing SQLite handle: %s", sqlite3_errstr(status));
765 goto unlink;
766 }
767
768 if (ret < 0) {
769 unlink:
770 if ((unlinkat(fd, r, 0) < 0) && (errno != ENOENT)) {
771 ERROR("Error removing partially initialised database: %s",
772 fr_syserror(errno));
773 }
774 close(fd);
775 return -1;
776 }
777 }
778
779 close(fd);
780 return 0;
781}
782
783static int mod_load(void)
784{
785 if (sqlite3_libversion_number() != SQLITE_VERSION_NUMBER) {
786 WARN("libsqlite version changed since the server was built");
787 WARN("linked: %s built: %s", sqlite3_libversion(), SQLITE_VERSION);
788 }
789 INFO("libsqlite version: %s", sqlite3_libversion());
790
791 return 0;
792}
793
794/* Exported to rlm_sql */
797 .common = {
798 .name = "sql_sqlite",
799 .magic = MODULE_MAGIC_INIT,
800 .inst_size = sizeof(rlm_sql_sqlite_t),
802 .onload = mod_load,
804 },
806 .sql_query_resume = sql_query_resume,
807 .sql_select_query_resume = sql_query_resume,
808 .sql_affected_rows = sql_affected_rows,
809 .sql_fetch_row = sql_fetch_row,
810 .sql_fields = sql_fields,
811 .sql_free_result = sql_free_result,
812 .sql_error = sql_error,
813 .sql_finish_query = sql_finish_query,
814 .sql_finish_select_query = sql_finish_query,
815 .trunk_io_funcs = {
816 .connection_alloc = sql_trunk_connection_alloc,
817 .request_mux = sql_trunk_request_mux,
818 .request_complete = sql_request_complete,
819 .request_fail = sql_request_fail
820 }
821};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
static int const char char buffer[256]
Definition acutest.h:576
va_end(args)
static int const char * fmt
Definition acutest.h:573
va_start(args, fmt)
#define RCSID(id)
Definition build.h:483
#define NDEBUG_UNUSED
Definition build.h:326
#define CC_NO_UBSAN(_sanitize)
Definition build.h:426
#define UNUSED
Definition build.h:315
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
conf_parser_flags_t flags
Flags which control parsing behaviour.
Definition cf_parse.h:585
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:256
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:418
@ CONF_FLAG_FILE_OUTPUT
File matching value must exist, and must be writable.
Definition cf_parse.h:426
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:579
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:70
CONF_PAIR * cf_pair_find_next(CONF_SECTION const *cs, CONF_PAIR const *prev, char const *attr)
Find a pair with a name matching attr, after specified pair.
Definition cf_util.c:1453
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition cf_util.c:1439
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1594
connection_state_t
Definition connection.h:45
@ CONNECTION_STATE_FAILED
Connection has failed.
Definition connection.h:54
@ CONNECTION_STATE_CONNECTED
File descriptor is open (ready for writing).
Definition connection.h:52
#define MEM(x)
Definition debug.h:36
#define ERROR(fmt,...)
Definition dhcpclient.c:41
#define DEBUG(fmt,...)
Definition dhcpclient.c:39
Test enumeration values.
Definition dict_test.h:92
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
ssize_t fr_mkdir(int *fd_out, char const *path, ssize_t len, mode_t mode, fr_mkdir_func_t func, void *uctx)
Create directories that are missing in the specified path.
Definition file.c:219
int fr_dirfd(int *dirfd, char const **filename, char const *pathname)
From a pathname, return fd and filename needed for *at() functions.
Definition file.c:412
#define PERROR(_fmt,...)
Definition log.h:228
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
Definition log.h:528
talloc_free(reap)
Stores all information relating to an event list.
Definition event.c:411
@ L_ERR
Error message.
Definition log.h:56
main_config_t const * main_config
Main server configuration.
Definition main_config.c:69
char const * raddb_dir
Path to raddb directory.
Definition main_config.h:78
long int ssize_t
unsigned char uint8_t
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
size_t fr_utf8_char(uint8_t const *str, ssize_t inlen)
Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8.
Definition print.c:39
static const conf_parser_t config[]
Definition base.c:183
#define fr_assert(_expr)
Definition rad_assert.h:38
#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
#define RETURN_MODULE_OK
Definition rcode.h:57
#define RETURN_MODULE_FAIL
Definition rcode.h:56
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
static int instantiate(module_inst_ctx_t const *mctx)
Definition rlm_rest.c:1310
Prototypes and functions for the SQL module.
fr_sql_query_status_t status
Status of the query.
Definition rlm_sql.h:138
trunk_connection_t * tconn
Trunk connection this query is being run on.
Definition rlm_sql.h:134
fr_sql_query_type_t type
Type of query.
Definition rlm_sql.h:137
char const * query_str
Query string to run.
Definition rlm_sql.h:136
request_t * request
Request this query relates to.
Definition rlm_sql.h:132
sql_rcode_t
Action to take at end of an SQL query.
Definition rlm_sql.h:44
@ RLM_SQL_ALT_QUERY
Key constraint violation, use an alternative query.
Definition rlm_sql.h:49
@ 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
@ SQL_QUERY_OTHER
Definition rlm_sql.h:115
#define RLM_SQL_RCODE_FLAGS_ALT_QUERY
Can distinguish between other errors and those resulting from a unique key violation.
Definition rlm_sql.h:164
rlm_sql_row_t row
Row data from the last query.
Definition rlm_sql.h:140
sql_rcode_t rcode
Result code.
Definition rlm_sql.h:139
trunk_request_t * treq
Trunk request for this query.
Definition rlm_sql.h:135
@ SQL_QUERY_FAILED
Failed to submit.
Definition rlm_sql.h:121
Definition rlm_sql.h:61
static void sql_request_complete(UNUSED request_t *request, void *preq, UNUSED void *rctx, UNUSED void *uctx)
static size_t sql_error(UNUSED TALLOC_CTX *ctx, sql_log_entry_t out[], NDEBUG_UNUSED size_t outlen, fr_sql_query_t *query_ctx)
Retrieves any errors associated with the query context.
sqlite_int64 sqlite3_int64
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 SQL_TRUNK_CONNECTION_ALLOC void sql_trunk_request_mux(UNUSED fr_event_list_t *el, trunk_connection_t *tconn, connection_t *conn, UNUSED void *uctx)
static void sql_print_error(sqlite3 *db, int status, char const *fmt,...))
Print an error to the global debug log.
rlm_sql_driver_t rlm_sql_sqlite
static connection_state_t _sql_connection_init(void **h, connection_t *conn, void *uctx)
char const * filename
static int sql_loadfile(TALLOC_CTX *ctx, sqlite3 *db, char const *filename)
static unlang_action_t sql_fetch_row(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
sqlite3_stmt * statement
static void _sql_connection_close(UNUSED fr_event_list_t *el, void *h, UNUSED void *uctx)
static const conf_parser_t driver_config[]
static sql_rcode_t sql_error_to_rcode(int status)
Convert an sqlite status code to an sql_rcode_t.
#define SQLITE_OPEN_NOMUTEX
#define BOOTSTRAP_MAX
static SQL_QUERY_RESUME void sql_request_fail(UNUSED request_t *request, void *preq, UNUSED void *rctx, UNUSED trunk_request_state_t state, UNUSED void *uctx)
static sql_rcode_t sql_finish_query(fr_sql_query_t *query_ctx, rlm_sql_config_t const *config)
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 mod_instantiate(module_inst_ctx_t const *mctx)
static sql_rcode_t sql_check_error(sqlite3 *db, int status)
Determine if an error occurred, and what type of error it was.
static void _sql_greatest(sqlite3_context *ctx, int num_values, sqlite3_value **values)
Macros to reduce boilerplate in trunk SQL drivers.
#define SQL_QUERY_RESUME
#define SQL_TRUNK_CONNECTION_ALLOC
Allocate an SQL trunk connection.
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:329
size_t inst_size
Size of the module's instance data.
Definition module.h:203
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
static char buff[sizeof("18446744073709551615")+3]
Definition size_tests.c:41
eap_aka_sim_process_conf_t * inst
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:194
module_instance_t * driver_submodule
Driver's submodule.
Definition rlm_sql.h:227
rlm_sql_config_t config
Definition rlm_sql.h:221
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
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
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
#define talloc_get_type_abort_const
Definition talloc.h:282
static const char * names[8]
Definition time.c:621
static int64_t fr_time_delta_to_sec(fr_time_delta_t delta)
Definition time.h:647
void trunk_request_signal_fail(trunk_request_t *treq)
Signal that a trunk request failed.
Definition trunk.c:2132
int trunk_connection_pop_request(trunk_request_t **treq_out, trunk_connection_t *tconn)
Pop a request off a connection's pending queue.
Definition trunk.c:3883
void trunk_request_signal_reapable(trunk_request_t *treq)
Signal that the request was written to a connection successfully, but no response is expected.
Definition trunk.c:2072
Associates request queues with a connection.
Definition trunk.c:134
Wraps a normal request.
Definition trunk.c:100
trunk_request_state_t
Used for sanity checks and to simplify freeing.
Definition trunk.h:161
close(uq->fd)
static fr_event_list_t * el
static fr_slen_t parent
Definition pair.h:851
int nonnull(2, 5))
static size_t char ** out
Definition value.h:997