2 * sql_db2.c IBM DB2 rlm_sql driver
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
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
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2000,2006 The FreeRADIUS server project
21 * Copyright 2000 Mike Machado <mike@innercite.com>
22 * Copyright 2000 Alan DeKok <aland@ox.org>
23 * Copyright 2001 Joerg Wendland <wendland@scan-plus.de>
27 * Modification of rlm_sql_db2 to handle IBM DB2 UDB V7
28 * by Joerg Wendland <wendland@scan-plus.de>
33 #include <freeradius-devel/radiusd.h>
34 #include <freeradius-devel/rad_assert.h>
42 typedef struct rlm_sql_conn {
48 static int _sql_socket_destructor(rlm_sql_db2_conn_t *conn)
50 DEBUG2("rlm_sql_db2: Socket destructor called, closing socket");
53 SQLDisconnect(conn->hdbc);
54 SQLFreeHandle(SQL_HANDLE_DBC, conn->hdbc);
58 SQLFreeHandle(SQL_HANDLE_ENV, conn->henv);
64 static sql_rcode_t sql_socket_init(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
67 rlm_sql_db2_conn_t *conn;
69 MEM(conn = handle->conn = talloc_zero(handle, rlm_sql_db2_conn_t));
70 talloc_set_destructor(conn, _sql_socket_destructor);
72 /* allocate handles */
73 SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(conn->henv));
74 SQLAllocHandle(SQL_HANDLE_DBC, conn->henv, &(conn->hdbc));
77 * The db2 API doesn't qualify arguments as const even when they should be.
80 SQLCHAR *server, *login, *password;
82 memcpy(&server, &config->sql_server, sizeof(server));
83 memcpy(&login, &config->sql_login, sizeof(login));
84 memcpy(&password, &config->sql_password, sizeof(password));
86 retval = SQLConnect(conn->hdbc,
92 if (retval != SQL_SUCCESS) {
93 ERROR("could not connect to DB2 server %s", config->sql_server);
101 static sql_rcode_t sql_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config, char const *query)
104 rlm_sql_db2_conn_t *conn;
108 /* allocate handle for statement */
109 SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &(conn->stmt));
114 memcpy(&db2_query, &query, sizeof(query));
116 retval = SQLExecDirect(conn->stmt, db2_query, SQL_NTS);
117 if(retval != SQL_SUCCESS) {
118 /* XXX Check if retval means we should return RLM_SQL_RECONNECT */
119 ERROR("Could not execute statement \"%s\"\n", query);
120 return RLM_SQL_ERROR;
127 static sql_rcode_t sql_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config, char const *query)
129 return sql_query(handle, config, query);
132 static int sql_num_fields(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
135 rlm_sql_db2_conn_t *conn;
138 SQLNumResultCols(conn->stmt, &c);
142 static sql_rcode_t sql_fetch_row(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
145 SQLINTEGER len, slen;
146 rlm_sql_row_t retval;
147 rlm_sql_db2_conn_t *conn;
151 c = sql_num_fields(handle, config);
152 retval = (rlm_sql_row_t)rad_malloc(c*sizeof(char*)+1);
153 memset(retval, 0, c*sizeof(char*)+1);
156 if(SQLFetch(conn->stmt) == SQL_NO_DATA_FOUND) {
161 for(i = 0; i < c; i++) {
162 /* get column length */
163 SQLColAttribute(conn->stmt, i+1, SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL, &len);
165 retval[i] = rad_malloc(len+1);
167 /* get the actual column */
168 SQLGetData(conn->stmt, i + 1, SQL_C_CHAR, retval[i], len+1, &slen);
169 if(slen == SQL_NULL_DATA) {
174 handle->row = retval;
178 for(i = 0; i < c; i++) {
183 return RLM_SQL_ERROR;
186 static sql_rcode_t sql_free_result(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
188 rlm_sql_db2_conn_t *conn;
190 SQLFreeHandle(SQL_HANDLE_STMT, conn->stmt);
195 /** Retrieves any errors associated with the connection handle
197 * @note Caller will free any memory allocated in ctx.
199 * @param ctx to allocate temporary error buffers in.
200 * @param out Array of sql_log_entrys to fill.
201 * @param outlen Length of out array.
202 * @param handle rlm_sql connection handle.
203 * @param config rlm_sql config.
204 * @return number of errors written to the sql_log_entry array.
206 static size_t sql_error(TALLOC_CTX *ctx, sql_log_entry_t out[], size_t outlen,
207 rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
213 rlm_sql_db2_conn_t *conn = handle->conn;
216 rad_assert(outlen > 0);
219 SQLGetDiagRec(SQL_HANDLE_STMT, conn->stmt, 1, (SQLCHAR *) state, &err,
220 (SQLCHAR *) errbuff, sizeof(errbuff), &rl);
221 if (errbuff[0] == '\0') return 0;
224 out[0].msg = talloc_asprintf(ctx, "%s: %s", state, errbuff);
229 static sql_rcode_t sql_finish_query(UNUSED rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
234 static sql_rcode_t sql_finish_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
236 return sql_finish_query(handle, config);
239 static int sql_affected_rows(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
242 rlm_sql_db2_conn_t *conn = handle->conn;
244 SQLRowCount(conn->stmt, &c);
249 /* Exported to rlm_sql */
250 extern rlm_sql_module_t rlm_sql_db2;
251 rlm_sql_module_t rlm_sql_db2 = {
252 .name = "rlm_sql_db2",
253 .sql_socket_init = sql_socket_init,
254 .sql_query = sql_query,
255 .sql_select_query = sql_select_query,
256 .sql_num_fields = sql_num_fields,
257 .sql_affected_rows = sql_affected_rows,
258 .sql_fetch_row = sql_fetch_row,
259 .sql_free_result = sql_free_result,
260 .sql_error = sql_error,
261 .sql_finish_query = sql_finish_query,
262 .sql_finish_select_query = sql_finish_select_query