7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 only, as published by
9 * the Free Software Foundation.
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.
16 * You should have received a copy of the GNU General Public License version 2
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Copyright 2007 Apple Inc.
23 #include <freeradius-devel/ident.h>
26 #include <freeradius-devel/radiusd.h>
34 typedef struct rlm_sql_sqlite_sock {
38 } rlm_sql_sqlite_sock;
41 /*************************************************************************
43 * Function: sql_create_socket
45 * Purpose: Establish connection to the db
47 *************************************************************************/
48 static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config)
51 rlm_sql_sqlite_sock *sqlite_sock;
54 if (!sqlsocket->conn) {
55 sqlsocket->conn = (rlm_sql_sqlite_sock *)rad_malloc(sizeof(rlm_sql_sqlite_sock));
56 if (!sqlsocket->conn) {
60 sqlite_sock = sqlsocket->conn;
61 memset(sqlite_sock, 0, sizeof(rlm_sql_sqlite_sock));
63 snprintf(buffer, sizeof(buffer), "%s/sqlite_radius_client_database",
65 radlog(L_INFO, "rlm_sql_sqlite: Opening sqlite database %s for #%d",
66 buffer, sqlsocket->id);
68 status = sqlite3_open(buffer, &sqlite_sock->pDb);
69 radlog(L_INFO, "rlm_sql_sqlite: sqlite3_open() = %d\n", status);
70 return (status != SQLITE_OK) * -1;
74 /*************************************************************************
76 * Function: sql_destroy_socket
78 * Purpose: Free socket and any private connection data
80 *************************************************************************/
81 static int sql_destroy_socket(SQLSOCK *sqlsocket, UNUSED SQL_CONFIG *config)
84 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
86 if (sqlite_sock && sqlite_sock->pDb) {
87 status = sqlite3_close(sqlite_sock->pDb);
88 radlog(L_INFO, "rlm_sql_sqlite: sqlite3_close() = %d\n", status);
91 radlog(L_INFO, "rlm_sql_sqlite: sql_destroy_socket noop.\n");
98 /*************************************************************************
100 * Function: sql_query
102 * Purpose: Issue a query to the database
104 *************************************************************************/
105 static int sql_query(SQLSOCK * sqlsocket, SQL_CONFIG *config, char *querystr)
108 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
111 if (config->sqltrace)
112 radlog(L_DBG,"rlm_sql_sqlite: query: %s", querystr);
113 if (sqlite_sock->pDb == NULL) {
114 radlog(L_ERR, "rlm_sql_sqlite: Socket not connected");
118 status = sqlite3_prepare(sqlite_sock->pDb, querystr, strlen(querystr), &sqlite_sock->pStmt, &zTail);
119 radlog(L_DBG, "rlm_sql_sqlite: sqlite3_prepare() = %d\n", status);
120 sqlite_sock->columnCount = 0;
122 return (status == SQLITE_OK) ? 0 : SQL_DOWN;
126 /*************************************************************************
128 * Function: sql_select_query
130 * Purpose: Issue a select query to the database
132 *************************************************************************/
133 static int sql_select_query(SQLSOCK *sqlsocket, SQL_CONFIG *config,
136 if (strstr(querystr, "nas") != NULL)
137 return sql_query(sqlsocket, config, querystr);
143 /*************************************************************************
145 * Function: sql_store_result
147 * Purpose: database specific store_result function. Returns a result
150 *************************************************************************/
151 static int sql_store_result(UNUSED SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
157 /*************************************************************************
159 * Function: sql_num_fields
161 * Purpose: database specific num_fields function. Returns number
162 * of columns from query
164 *************************************************************************/
165 static int sql_num_fields(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
167 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
169 if (sqlite_sock->pStmt)
170 return sqlite3_column_count(sqlite_sock->pStmt);
176 /*************************************************************************
178 * Function: sql_num_rows
180 * Purpose: database specific num_rows. Returns number of rows in
183 *************************************************************************/
184 static int sql_num_rows(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
186 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
188 if (sqlite_sock->pStmt)
189 return sqlite3_data_count(sqlite_sock->pStmt);
195 /*************************************************************************
196 * Function: sql_free_rowdata
197 *************************************************************************/
198 static void sql_free_rowdata(SQLSOCK * sqlsocket, int colcount)
200 char **rowdata = sqlsocket->row;
203 if (rowdata != NULL) {
204 for (colindex = 0; colindex < colcount; colindex++) {
205 if (rowdata[colindex] != NULL) {
206 free(rowdata[colindex]);
207 rowdata[colindex] = NULL;
210 free(sqlsocket->row);
211 sqlsocket->row = NULL;
216 /*************************************************************************
218 * Function: sql_fetch_row
220 * Purpose: database specific fetch_row. Returns a SQL_ROW struct
221 * with all the data for the query in 'sqlsocket->row'. Returns
222 * 0 on success, -1 on failure, SQL_DOWN if database is down.
224 *************************************************************************/
225 static int sql_fetch_row(SQLSOCK * sqlsocket, SQL_CONFIG *config)
228 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
236 int ret_blob_size = 0;
237 char **rowdata = NULL;
238 const unsigned char *textStr;
241 status = sqlite3_step(sqlite_sock->pStmt);
242 radlog(L_DBG, "rlm_sql_sqlite: sqlite3_step = %d\n", status);
243 if (status == SQLITE_DONE) {
244 sql_free_rowdata(sqlsocket, sqlite_sock->columnCount);
247 else if (status == SQLITE_ROW) {
248 if (sqlite_sock->columnCount == 0) {
249 sqlite_sock->columnCount = sql_num_fields(sqlsocket, config);
251 colcount = sqlite_sock->columnCount;
255 sql_free_rowdata(sqlsocket, colcount);
257 ret_blob_size = sizeof(char *) * (colcount+1);
258 rowdata = (char **)rad_malloc(ret_blob_size); /* Space for pointers */
259 if (rowdata != NULL) {
260 memset(rowdata, 0, ret_blob_size); /* NULL-pad the pointers */
261 sqlsocket->row = rowdata;
264 for (colindex = 0; colindex < colcount; colindex++)
266 coltype = sqlite3_column_type(sqlite_sock->pStmt, colindex);
270 colintvalue = sqlite3_column_int(sqlite_sock->pStmt, colindex);
271 snprintf(intStr, sizeof(intStr), "%d", colintvalue);
272 rowdata[colindex] = strdup(intStr);
276 textStr = sqlite3_column_text(sqlite_sock->pStmt, colindex);
278 rowdata[colindex] = strdup((const char *)textStr);
282 blob = sqlite3_column_blob(sqlite_sock->pStmt, colindex);
284 blobLen = sqlite3_column_bytes(sqlite_sock->pStmt, colindex);
285 rowdata[colindex] = (char *)rad_malloc(blobLen + 1);
286 if (rowdata[colindex] != NULL) {
287 memcpy(rowdata[colindex], blob, blobLen);
304 /*************************************************************************
306 * Function: sql_free_result
308 * Purpose: database specific free_result. Frees memory allocated
311 *************************************************************************/
312 static int sql_free_result(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
315 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
317 if (sqlite_sock->pStmt != NULL) {
318 sql_free_rowdata(sqlsocket, sqlite_sock->columnCount);
319 status = sqlite3_finalize(sqlite_sock->pStmt);
320 sqlite_sock->pStmt = NULL;
321 radlog(L_DBG, "rlm_sql_sqlite: sqlite3_finalize() = %d\n", status);
328 /*************************************************************************
330 * Function: sql_error
332 * Purpose: database specific error. Returns error associated with
335 *************************************************************************/
336 static const char *sql_error(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
342 /*************************************************************************
344 * Function: sql_close
346 * Purpose: database specific close. Closes an open database
349 *************************************************************************/
350 static int sql_close(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
353 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
355 if (sqlite_sock && sqlite_sock->pDb) {
356 status = sqlite3_close(sqlite_sock->pDb);
357 sqlite_sock->pDb = NULL;
364 /*************************************************************************
366 * Function: sql_finish_query
368 * Purpose: End the query, such as freeing memory
370 *************************************************************************/
371 static int sql_finish_query(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
374 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
376 if (sqlite_sock->pStmt) {
377 status = sqlite3_finalize(sqlite_sock->pStmt);
378 sqlite_sock->pStmt = NULL;
379 radlog(L_DBG, "rlm_sql_sqlite: sqlite3_finalize() = %d\n", status);
386 /*************************************************************************
388 * Function: sql_finish_select_query
390 * Purpose: End the select query, such as freeing memory or result
392 *************************************************************************/
393 static int sql_finish_select_query(SQLSOCK * sqlsocket, SQL_CONFIG *config)
395 return sql_finish_query(sqlsocket, config);
399 /*************************************************************************
401 * Function: sql_affected_rows
403 * Purpose: End the select query, such as freeing memory or result
405 *************************************************************************/
406 static int sql_affected_rows(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
412 /* Exported to rlm_sql */
413 rlm_sql_module_t rlm_sql_sqlite = {
427 sql_finish_select_query,