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;
55 if (!sqlsocket->conn) {
56 sqlsocket->conn = (rlm_sql_sqlite_sock *)rad_malloc(sizeof(rlm_sql_sqlite_sock));
57 if (!sqlsocket->conn) {
61 sqlite_sock = sqlsocket->conn;
62 memset(sqlite_sock, 0, sizeof(rlm_sql_sqlite_sock));
64 filename = config->sql_file;
66 snprintf(buffer, sizeof(buffer), "%s/sqlite_radius_client_database",
70 radlog(L_INFO, "rlm_sql_sqlite: Opening sqlite database %s for #%d",
71 filename, sqlsocket->id);
73 status = sqlite3_open(filename, &sqlite_sock->pDb);
74 radlog(L_INFO, "rlm_sql_sqlite: sqlite3_open() = %d\n", status);
75 return (status != SQLITE_OK) * -1;
79 /*************************************************************************
81 * Function: sql_destroy_socket
83 * Purpose: Free socket and any private connection data
85 *************************************************************************/
86 static int sql_destroy_socket(SQLSOCK *sqlsocket, UNUSED SQL_CONFIG *config)
89 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
91 if (sqlite_sock && sqlite_sock->pDb) {
92 status = sqlite3_close(sqlite_sock->pDb);
93 radlog(L_INFO, "rlm_sql_sqlite: sqlite3_close() = %d\n", status);
96 radlog(L_INFO, "rlm_sql_sqlite: sql_destroy_socket noop.\n");
103 /*************************************************************************
105 * Function: sql_query
107 * Purpose: Issue a query to the database
109 *************************************************************************/
110 static int sql_query(SQLSOCK * sqlsocket, SQL_CONFIG *config, char *querystr)
113 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
116 if (config->sqltrace)
117 radlog(L_DBG,"rlm_sql_sqlite: query: %s", querystr);
118 if (sqlite_sock->pDb == NULL) {
119 radlog(L_ERR, "rlm_sql_sqlite: Socket not connected");
123 status = sqlite3_prepare(sqlite_sock->pDb, querystr, strlen(querystr), &sqlite_sock->pStmt, &zTail);
124 radlog(L_DBG, "rlm_sql_sqlite: sqlite3_prepare() = %d\n", status);
125 sqlite_sock->columnCount = 0;
127 return (status == SQLITE_OK) ? 0 : SQL_DOWN;
131 /*************************************************************************
133 * Function: sql_select_query
135 * Purpose: Issue a select query to the database
137 *************************************************************************/
138 static int sql_select_query(SQLSOCK *sqlsocket, SQL_CONFIG *config,
141 if (strstr(querystr, "nas") != NULL)
142 return sql_query(sqlsocket, config, querystr);
148 /*************************************************************************
150 * Function: sql_store_result
152 * Purpose: database specific store_result function. Returns a result
155 *************************************************************************/
156 static int sql_store_result(UNUSED SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
162 /*************************************************************************
164 * Function: sql_num_fields
166 * Purpose: database specific num_fields function. Returns number
167 * of columns from query
169 *************************************************************************/
170 static int sql_num_fields(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
172 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
174 if (sqlite_sock->pStmt)
175 return sqlite3_column_count(sqlite_sock->pStmt);
181 /*************************************************************************
183 * Function: sql_num_rows
185 * Purpose: database specific num_rows. Returns number of rows in
188 *************************************************************************/
189 static int sql_num_rows(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
191 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
193 if (sqlite_sock->pStmt)
194 return sqlite3_data_count(sqlite_sock->pStmt);
200 /*************************************************************************
201 * Function: sql_free_rowdata
202 *************************************************************************/
203 static void sql_free_rowdata(SQLSOCK * sqlsocket, int colcount)
205 char **rowdata = sqlsocket->row;
208 if (rowdata != NULL) {
209 for (colindex = 0; colindex < colcount; colindex++) {
210 if (rowdata[colindex] != NULL) {
211 free(rowdata[colindex]);
212 rowdata[colindex] = NULL;
215 free(sqlsocket->row);
216 sqlsocket->row = NULL;
221 /*************************************************************************
223 * Function: sql_fetch_row
225 * Purpose: database specific fetch_row. Returns a SQL_ROW struct
226 * with all the data for the query in 'sqlsocket->row'. Returns
227 * 0 on success, -1 on failure, SQL_DOWN if database is down.
229 *************************************************************************/
230 static int sql_fetch_row(SQLSOCK * sqlsocket, SQL_CONFIG *config)
233 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
241 int ret_blob_size = 0;
242 char **rowdata = NULL;
243 const unsigned char *textStr;
246 status = sqlite3_step(sqlite_sock->pStmt);
247 radlog(L_DBG, "rlm_sql_sqlite: sqlite3_step = %d\n", status);
248 if (status == SQLITE_DONE) {
249 sql_free_rowdata(sqlsocket, sqlite_sock->columnCount);
252 else if (status == SQLITE_ROW) {
253 if (sqlite_sock->columnCount == 0) {
254 sqlite_sock->columnCount = sql_num_fields(sqlsocket, config);
256 colcount = sqlite_sock->columnCount;
260 sql_free_rowdata(sqlsocket, colcount);
262 ret_blob_size = sizeof(char *) * (colcount+1);
263 rowdata = (char **)rad_malloc(ret_blob_size); /* Space for pointers */
264 if (rowdata != NULL) {
265 memset(rowdata, 0, ret_blob_size); /* NULL-pad the pointers */
266 sqlsocket->row = rowdata;
269 for (colindex = 0; colindex < colcount; colindex++)
271 coltype = sqlite3_column_type(sqlite_sock->pStmt, colindex);
275 colintvalue = sqlite3_column_int(sqlite_sock->pStmt, colindex);
276 snprintf(intStr, sizeof(intStr), "%d", colintvalue);
277 rowdata[colindex] = strdup(intStr);
281 textStr = sqlite3_column_text(sqlite_sock->pStmt, colindex);
283 rowdata[colindex] = strdup((const char *)textStr);
287 blob = sqlite3_column_blob(sqlite_sock->pStmt, colindex);
289 blobLen = sqlite3_column_bytes(sqlite_sock->pStmt, colindex);
290 rowdata[colindex] = (char *)rad_malloc(blobLen + 1);
291 if (rowdata[colindex] != NULL) {
292 memcpy(rowdata[colindex], blob, blobLen);
309 /*************************************************************************
311 * Function: sql_free_result
313 * Purpose: database specific free_result. Frees memory allocated
316 *************************************************************************/
317 static int sql_free_result(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
320 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
322 if (sqlite_sock->pStmt != NULL) {
323 sql_free_rowdata(sqlsocket, sqlite_sock->columnCount);
324 status = sqlite3_finalize(sqlite_sock->pStmt);
325 sqlite_sock->pStmt = NULL;
326 radlog(L_DBG, "rlm_sql_sqlite: sqlite3_finalize() = %d\n", status);
333 /*************************************************************************
335 * Function: sql_error
337 * Purpose: database specific error. Returns error associated with
340 *************************************************************************/
341 static const char *sql_error(UNUSED SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
347 /*************************************************************************
349 * Function: sql_close
351 * Purpose: database specific close. Closes an open database
354 *************************************************************************/
355 static int sql_close(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
358 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
360 if (sqlite_sock && sqlite_sock->pDb) {
361 status = sqlite3_close(sqlite_sock->pDb);
362 sqlite_sock->pDb = NULL;
369 /*************************************************************************
371 * Function: sql_finish_query
373 * Purpose: End the query, such as freeing memory
375 *************************************************************************/
376 static int sql_finish_query(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
379 rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
381 if (sqlite_sock->pStmt) {
382 status = sqlite3_finalize(sqlite_sock->pStmt);
383 sqlite_sock->pStmt = NULL;
384 radlog(L_DBG, "rlm_sql_sqlite: sqlite3_finalize() = %d\n", status);
391 /*************************************************************************
393 * Function: sql_finish_select_query
395 * Purpose: End the select query, such as freeing memory or result
397 *************************************************************************/
398 static int sql_finish_select_query(SQLSOCK * sqlsocket, SQL_CONFIG *config)
400 return sql_finish_query(sqlsocket, config);
404 /*************************************************************************
406 * Function: sql_affected_rows
408 * Purpose: End the select query, such as freeing memory or result
410 *************************************************************************/
411 static int sql_affected_rows(UNUSED SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
417 /* Exported to rlm_sql */
418 rlm_sql_module_t rlm_sql_sqlite = {
432 sql_finish_select_query,