cca14b8999a80241f0a6458f6b91ad85cb8ac075
[freeradius.git] / src / modules / rlm_sql / sql_module.c
1 /*
2  * sql_module.c - MySQL routines for FreeRADIUS SQL module 
3  *
4  * Mike Machado <mike@innercite.com>
5  */
6
7 #include <stdio.h>
8 #include <sys/stat.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include        "radiusd.h"
13 #include        "rlm_sql.h"
14
15
16 /*************************************************************************
17  *
18  *      Function: sql_connect
19  *
20  *      Purpose: Connect to the sql server
21  *
22  *************************************************************************/
23 int sql_connect(void) {
24
25         MYSQL MyAuthConn;
26         MYSQL MyAcctConn;
27
28         /* Connect to the database server */
29         mysql_init(&MyAuthConn);
30         if (!(sql->AuthSock->conn = mysql_real_connect(&MyAuthConn, sql->config.sql_server, sql->config.sql_login, sql->config.sql_password, sql->config.sql_db, 0, NULL, 0))) {
31              log(L_ERR, "Init: Couldn't connect authentication socket to MySQL server on %s as %s", sql->config.sql_server, sql->config.sql_login);
32              sql->AuthSock->conn = NULL;
33         }
34         mysql_init(&MyAcctConn);
35         if (!(sql->AcctSock->conn = mysql_real_connect(&MyAcctConn, sql->config.sql_server, sql->config.sql_login, sql->config.sql_password, sql->config.sql_db, 0, NULL, 0))) {
36              log(L_ERR, "Init: Couldn't connect accounting socket to MySQL server on %s as %s", sql->config.sql_server, sql->config.sql_login);
37              sql->AcctSock->conn = NULL;
38         }
39            
40        return 0;
41 }
42
43  
44
45 /*************************************************************************
46  *
47  *      Function: sql_checksocket
48  *
49  *      Purpose: Make sure our database connection is up
50  *
51  *************************************************************************/
52 int sql_checksocket(const char *facility) {
53
54         if ((strncmp(facility, "Auth", 4) == 0)) {
55                 if (sql->AuthSock->conn == NULL) {
56
57                         MYSQL MyAuthConn;
58                         if (sql->config.sql_keepopen)
59                                 log(L_ERR, "%s: Keepopen set but had to reconnect to MySQL", facility);
60                         /* Connect to the database server */
61                         mysql_init(&MyAuthConn);
62                         if (!(sql->AuthSock->conn = mysql_real_connect(&MyAuthConn, sql->config.sql_server, sql->config.sql_login, sql->config.sql_password, sql->config.sql_db, 0, NULL, 0))) {
63                                 log(L_ERR, "Auth: Couldn't connect authentication socket to MySQL server on %s as %s", sql->config.sql_server, sql->config.sql_login);
64                                 sql->AuthSock->conn = NULL;
65                                 return 0;
66                         }
67                 }
68
69         } else {
70                 if (sql->AcctSock->conn == NULL) {
71                         MYSQL MyAcctConn;
72                         if (sql->config.sql_keepopen)
73                                 log(L_ERR, "%s: Keepopen set but had to reconnect to MySQL", facility);
74                         /* Connect to the database server */
75                         mysql_init(&MyAcctConn);
76                         if (!(sql->AcctSock->conn = mysql_real_connect(&MyAcctConn, sql->config.sql_server, sql->config.sql_login, sql->config.sql_password, sql->config.sql_db, 0, NULL, 0))) {
77                                 log(L_ERR, "Acct: Couldn't connect accounting socket to MySQL server on %s as %s", sql->config.sql_server, sql->config.sql_login);
78                                 sql->AcctSock->conn = NULL;
79                                 return 0;
80                         }
81                 }
82
83         }
84
85         return 1;
86
87 }
88
89
90 /*************************************************************************
91  *
92  *      Function: sql_query
93  *
94  *      Purpose: Issue a query to the database
95  *
96  *************************************************************************/
97 int sql_query(SQLSOCK *socket, char *querystr) {
98
99  if (sql->config.sqltrace)
100         DEBUG(querystr);
101  return mysql_query(socket->conn, querystr);
102
103 }
104
105
106 /*************************************************************************
107  *
108  *      Function: sql_select_query
109  *
110  *      Purpose: Issue a select query to the database
111  *
112  *************************************************************************/
113 int sql_select_query(SQLSOCK *socket, char *querystr) {
114
115  if (sql->config.sqltrace)
116         DEBUG(querystr);
117  mysql_query(socket->conn, querystr);
118  if (sql_store_result(socket) && sql_num_fields(socket)) 
119         return 0;
120  else
121         return 1;
122
123 }
124
125
126 /*************************************************************************
127  *
128  *      Function: sql_store_result
129  *
130  *      Purpose: database specific store_result function. Returns a result
131  *               set for the query.
132  *
133  *************************************************************************/
134 int sql_store_result(SQLSOCK *socket) {
135
136         if (!(socket->result = mysql_store_result(socket->conn))) {
137                 log(L_ERR,"MYSQL Error: Cannot get result");
138                 log(L_ERR,"MYSQL error: %s",mysql_error(socket->conn));
139                 sql_close(socket);
140                 return 0;
141         }
142         return 1;
143
144 }
145
146
147 /*************************************************************************
148  *
149  *      Function: sql_num_fields
150  *
151  *      Purpose: database specific num_fields function. Returns number
152  *               of columns from query
153  *
154  *************************************************************************/
155 int sql_num_fields(SQLSOCK *socket) {
156
157         int     num = 0;
158         if (!(num = mysql_num_fields(socket->conn))) {
159                 log(L_ERR,"MYSQL Error: Cannot get result");
160                 log(L_ERR,"MYSQL error: %s",mysql_error(socket->conn));
161                 sql_close(socket);
162         }
163         return num;
164 }
165
166
167 /*************************************************************************
168  *
169  *      Function: sql_num_rows
170  *
171  *      Purpose: database specific num_rows. Returns number of rows in
172  *               query
173  *
174  *************************************************************************/
175 int sql_num_rows(SQLSOCK *socket) {
176
177     return mysql_num_rows(socket->result);
178
179 }
180
181
182 /*************************************************************************
183  *
184  *      Function: sql_fetch_row
185  *
186  *      Purpose: database specific fetch_row. Returns a SQL_RES struct
187  *               with all the data for the query
188  *
189  *************************************************************************/
190 SQL_ROW sql_fetch_row(SQLSOCK *socket) {
191
192    return mysql_fetch_row(socket->result);
193
194 }
195
196
197
198 /*************************************************************************
199  *
200  *      Function: sql_free_result
201  *
202  *      Purpose: database specific free_result. Frees memory allocated
203  *               for a result set
204  *
205  *************************************************************************/
206 void sql_free_result(SQLSOCK *socket) {
207
208    mysql_free_result(socket->result);
209
210 }
211
212
213
214 /*************************************************************************
215  *
216  *      Function: sql_error
217  *
218  *      Purpose: database specific error. Returns error associated with
219  *               connection
220  *
221  *************************************************************************/
222 char *sql_error(SQLSOCK *socket) {
223
224   return (mysql_error(socket->conn));
225
226 }
227
228
229 /*************************************************************************
230  *
231  *      Function: sql_close
232  *
233  *      Purpose: database specific close. Closes an open database
234  *               connection
235  *
236  *************************************************************************/
237 void sql_close(SQLSOCK *socket) {
238
239    mysql_close(socket->conn);
240
241 }
242
243
244 /*************************************************************************
245  *
246  *      Function: sql_finish_query
247  *
248  *      Purpose: End the query, such as freeing memory
249  *
250  *************************************************************************/
251 void sql_finish_query(SQLSOCK *socket) {
252
253 }
254
255
256
257 /*************************************************************************
258  *
259  *      Function: sql_finish_select_query
260  *
261  *      Purpose: End the select query, such as freeing memory or result
262  *
263  *************************************************************************/
264 void sql_finish_select_query(SQLSOCK *socket) {
265
266    sql_free_result(socket);
267 }
268
269
270 /*************************************************************************
271  *
272  *      Function: sql_affected_rows
273  *
274  *      Purpose: End the select quh as freeing memory or result
275  *
276  *************************************************************************/
277 int sql_affected_rows(SQLSOCK *socket) {
278    int rows;
279
280    rows = mysql_affected_rows(socket->conn);
281    return rows;
282 }
283
284
285 /*************************************************************************
286  *
287  *      Function: sql_escape_string
288  *
289  *      Purpose: strdup() with the added feature of escaping binary
290  *              data in the string to safely fit into an SQL query
291  *
292  *************************************************************************/
293 char *sql_escape_string(const char *from) {
294         char *to;
295
296         if(from==NULL) 
297                 return NULL;
298         if((to=malloc((strlen(from)*2) + 1)) == NULL)   
299                 return NULL;
300         mysql_escape_string(to,from,strlen(from));
301         return to;
302 }