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 2009 Gabriel Blanchard gabe@teksavvy.com
23 #include <freeradius-devel/ident.h>
26 #include <freeradius-devel/radiusd.h>
35 static int query_timeout_handler(void *dbproc);
36 static int err_handler(UNUSED DBPROCESS *dbproc, UNUSED int severity, UNUSED int dberr, UNUSED int oserr, char *dberrstr, char *oserrstr);
38 // As defined in tds.h
39 #define TDS_INT_CONTINUE 1
40 #define TDS_INT_CANCEL 2
41 #define TDS_INT_TIMEOUT 3
43 typedef struct rlm_sql_freetds_sock {
45 } rlm_sql_freetds_sock;
48 * FreeTDS calls this handler when dbsqlexec() or dbsqlok() blocks every seconds
49 * This ensures that FreeTDS doesn't stay stuck on the same query for ever.
51 static int query_timeout_handler(void *dbproc) {
52 return TDS_INT_CONTINUE;
55 static int err_handler(UNUSED DBPROCESS *dbproc, UNUSED int severity, UNUSED int dberr, UNUSED int oserr, char *dberrstr, char *oserrstr)
57 radlog(L_ERR, "rlm_sql_freetds: FreeTDS error: %s\n", dberrstr);
58 radlog(L_ERR, "rlm_sql_freetds: OS error: %s\n", oserrstr);
62 /*************************************************************************
64 * Function: sql_create_socket
66 * Purpose: Establish connection to the db
68 *************************************************************************/
69 static int sql_init_socket(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
72 rlm_sql_freetds_sock *freetds_sock;
75 handle->conn = (rlm_sql_freetds_sock *)rad_malloc(sizeof(struct rlm_sql_freetds_sock));
81 if (dbinit() == FAIL) {
82 radlog(L_ERR, "rlm_sql_freetds: Unable to init FreeTDS");
86 dbsetversion(DBVERSION_80);
87 dberrhandle(err_handler);
89 // Timeout so that FreeTDS doesn't wait for ever.
90 dbsetlogintime((unsigned long)config->query_timeout);
91 dbsettime((unsigned long)config->query_timeout);
93 freetds_sock = handle->conn;
94 memset(freetds_sock, 0, sizeof(*freetds_sock));
96 DEBUG("rlm_sql_freetds (%s): Starting connect to FreeTDS/MSSQL server", config->xlat_name);
98 if (!(login = dblogin())) {
99 radlog(L_ERR, "rlm_sql_freetds (%s): Unable to allocate login record", config->xlat_name);
103 DBSETLUSER(login, config->sql_login);
104 DBSETLPWD(login, config->sql_password);
106 if ((freetds_sock->dbproc = dbopen(login, config->sql_server)) == FAIL) {
107 radlog(L_ERR, "rlm_sql_freetds (%s): Unable to connect to FreeTDS/MSSQL server %s@%s",
108 config->xlat_name, config->sql_login, config->sql_server);
115 if ((dbuse(freetds_sock->dbproc, config->sql_db)) == FAIL) {
116 radlog(L_ERR, "rlm_sql_freetds (%s): Unable to select database on FreeTDS/MSSQL server %s@%s:%s",
117 config->xlat_name, config->sql_login, config->sql_server, config->sql_db);
121 /* I know this may look strange, but it sets a pointer to
122 the freetds_sock struct so that it can be used within the
123 query_timeout_handler function to be able to timeout properly */
124 dbsetinterrupt(freetds_sock->dbproc, query_timeout_handler, query_timeout_handler);
125 dbsetuserdata(freetds_sock->dbproc, (BYTE *)freetds_sock);
131 /*************************************************************************
133 * Function: sql_destroy_socket
135 * Purpose: Free socket and any private connection data
137 *************************************************************************/
138 static int sql_destroy_socket(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
147 /*************************************************************************
149 * Function: sql_query
151 * Purpose: Issue a query to the database
153 *************************************************************************/
154 static int sql_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config, char *querystr)
156 rlm_sql_freetds_sock *freetds_sock = handle->conn;
158 if (freetds_sock->dbproc == NULL || DBDEAD(freetds_sock->dbproc)) {
159 radlog(L_ERR, "rlm_sql_freetds (%s): Socket not connected", config->xlat_name);
163 if ((dbcmd(freetds_sock->dbproc, querystr)) == FAIL) {
164 radlog(L_ERR, "rlm_sql_freetds (%s): Unable to allocate SQL query", config->xlat_name);
168 if ((dbsqlexec(freetds_sock->dbproc)) == FAIL) {
169 radlog(L_ERR, "rlm_sql_freetds (%s): SQL query failed", config->xlat_name);
177 /*************************************************************************
179 * Function: sql_select_query
181 * Purpose: Issue a select query to the database
183 *************************************************************************/
184 static int sql_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config, char *querystr)
186 radlog(L_ERR, "rlm_sql_freetds sql_select_query(): unsupported");
191 /*************************************************************************
193 * Function: sql_store_result
195 * Purpose: database specific store_result function. Returns a result
198 *************************************************************************/
199 static int sql_store_result(UNUSED rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
201 radlog(L_ERR, "rlm_sql_freetds sql_store_result(): unsupported");
206 /*************************************************************************
208 * Function: sql_num_fields
210 * Purpose: database specific num_fields function. Returns number
211 * of columns from query
213 *************************************************************************/
214 static int sql_num_fields(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
216 rlm_sql_freetds_sock *freetds_sock = handle->conn;
218 return dbnumcols(freetds_sock->dbproc);
222 /*************************************************************************
224 * Function: sql_num_rows
226 * Purpose: database specific num_rows. Returns number of rows in
229 *************************************************************************/
230 static int sql_num_rows(UNUSED rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
236 /*************************************************************************
238 * Function: sql_fetch_row
240 * Purpose: database specific fetch_row. Returns a rlm_sql_row_t struct
241 * with all the data for the query in 'handle->row'. Returns
242 * 0 on success, -1 on failure, SQL_DOWN if database is down.
244 *************************************************************************/
245 static int sql_fetch_row(UNUSED rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
251 /*************************************************************************
253 * Function: sql_free_result
255 * Purpose: database specific free_result. Frees memory allocated
258 *************************************************************************/
259 static int sql_free_result(UNUSED rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
266 /*************************************************************************
268 * Function: sql_error
270 * Purpose: database specific error. Returns error associated with
273 *************************************************************************/
274 static const char *sql_error(UNUSED rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
280 /*************************************************************************
282 * Function: sql_close
284 * Purpose: database specific close. Closes an open database
287 *************************************************************************/
288 static int sql_close(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
290 rlm_sql_freetds_sock *freetds_sock = handle->conn;
292 if (freetds_sock && freetds_sock->dbproc){
293 dbclose(freetds_sock->dbproc);
294 freetds_sock->dbproc = NULL;
301 /*************************************************************************
303 * Function: sql_finish_query
305 * Purpose: End the query, such as freeing memory
307 *************************************************************************/
308 static int sql_finish_query(UNUSED rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
315 /*************************************************************************
317 * Function: sql_finish_select_query
319 * Purpose: End the select query, such as freeing memory or result
321 *************************************************************************/
322 static int sql_finish_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
324 return sql_finish_query(handle, config);
328 /*************************************************************************
330 * Function: sql_affected_rows
332 * Purpose: End the select query, such as freeing memory or result
334 *************************************************************************/
335 static int sql_affected_rows(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
337 rlm_sql_freetds_sock *freetds_sock = handle->conn;
339 return dbcount(freetds_sock->dbproc);
343 /* Exported to rlm_sql */
344 rlm_sql_module_t rlm_sql_freetds = {
358 sql_finish_select_query,