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");
52 if (conn->dbc_handle) {
53 SQLDisconnect(conn->dbc_handle);
54 SQLFreeHandle(SQL_HANDLE_DBC, conn->dbc_handle);
57 if (conn->env_handle) SQLFreeHandle(SQL_HANDLE_ENV, conn->env_handle);
62 static sql_rcode_t sql_socket_init(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
65 rlm_sql_db2_conn_t *conn;
67 MEM(conn = handle->conn = talloc_zero(handle, rlm_sql_db2_conn_t));
68 talloc_set_destructor(conn, _sql_socket_destructor);
70 /* Allocate handles */
71 SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(conn->env_handle));
72 SQLAllocHandle(SQL_HANDLE_DBC, conn->env_handle, &(conn->dbc_handle));
75 * The db2 API doesn't qualify arguments as const even when they should be.
78 SQLCHAR *server, *login, *password;
80 memcpy(&server, &config->sql_server, sizeof(server));
81 memcpy(&login, &config->sql_login, sizeof(login));
82 memcpy(&password, &config->sql_password, sizeof(password));
84 retval = SQLConnect(conn->dbc_handle,
90 if (retval != SQL_SUCCESS) {
91 ERROR("could not connect to DB2 server %s", config->sql_server);
99 static sql_rcode_t sql_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config, char const *query)
102 rlm_sql_db2_conn_t *conn;
106 /* allocate handle for statement */
107 SQLAllocHandle(SQL_HANDLE_STMT, conn->dbc_handle, &(conn->stmt));
112 memcpy(&db2_query, &query, sizeof(query));
114 retval = SQLExecDirect(conn->stmt, db2_query, SQL_NTS);
115 if(retval != SQL_SUCCESS) {
116 /* XXX Check if retval means we should return RLM_SQL_RECONNECT */
117 ERROR("Could not execute statement \"%s\"", query);
118 return RLM_SQL_ERROR;
125 static sql_rcode_t sql_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config, char const *query)
127 return sql_query(handle, config, query);
130 static int sql_num_fields(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
133 rlm_sql_db2_conn_t *conn;
136 SQLNumResultCols(conn->stmt, &c);
140 static sql_rcode_t sql_fields(char const **out[], rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
142 rlm_sql_db2_conn_t *conn = handle->conn;
144 SQLSMALLINT fields, len, i;
149 SQLNumResultCols(conn->stmt, &fields);
150 if (fields == 0) return RLM_SQL_ERROR;
152 MEM(names = talloc_array(handle, char const *, fields));
154 for (i = 0; i < fields; i++) {
157 switch (SQLColAttribute(conn->stmt, i, SQL_DESC_BASE_COLUMN_NAME,
158 field, sizeof(field), &len, NULL)) {
159 case SQL_INVALID_HANDLE:
161 ERROR("Failed retrieving field name at index %i", i);
163 return RLM_SQL_ERROR;
169 MEM(p = talloc_array(names, char, (size_t)len + 1));
170 strlcpy(p, field, (size_t)len + 1);
178 static sql_rcode_t sql_fetch_row(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
181 SQLINTEGER len, slen;
182 rlm_sql_row_t retval;
183 rlm_sql_db2_conn_t *conn;
187 c = sql_num_fields(handle, config);
188 retval = (rlm_sql_row_t)rad_malloc(c*sizeof(char*)+1);
189 memset(retval, 0, c*sizeof(char*)+1);
192 if(SQLFetch(conn->stmt) == SQL_NO_DATA_FOUND) {
197 for(i = 0; i < c; i++) {
198 /* get column length */
199 SQLColAttribute(conn->stmt, i+1, SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL, &len);
201 retval[i] = rad_malloc(len+1);
203 /* get the actual column */
204 SQLGetData(conn->stmt, i + 1, SQL_C_CHAR, retval[i], len+1, &slen);
205 if(slen == SQL_NULL_DATA) {
210 handle->row = retval;
214 for(i = 0; i < c; i++) {
219 return RLM_SQL_ERROR;
222 static sql_rcode_t sql_free_result(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
224 rlm_sql_db2_conn_t *conn;
226 SQLFreeHandle(SQL_HANDLE_STMT, conn->stmt);
231 /** Retrieves any errors associated with the connection handle
233 * @note Caller will free any memory allocated in ctx.
235 * @param ctx to allocate temporary error buffers in.
236 * @param out Array of sql_log_entrys to fill.
237 * @param outlen Length of out array.
238 * @param handle rlm_sql connection handle.
239 * @param config rlm_sql config.
240 * @return number of errors written to the sql_log_entry array.
242 static size_t sql_error(TALLOC_CTX *ctx, sql_log_entry_t out[], size_t outlen,
243 rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
249 rlm_sql_db2_conn_t *conn = handle->conn;
252 rad_assert(outlen > 0);
255 SQLGetDiagRec(SQL_HANDLE_STMT, conn->stmt, 1, (SQLCHAR *) state, &err,
256 (SQLCHAR *) errbuff, sizeof(errbuff), &rl);
257 if (errbuff[0] == '\0') return 0;
260 out[0].msg = talloc_asprintf(ctx, "%s: %s", state, errbuff);
265 static sql_rcode_t sql_finish_query(UNUSED rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
270 static sql_rcode_t sql_finish_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
272 return sql_finish_query(handle, config);
275 static int sql_affected_rows(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
278 rlm_sql_db2_conn_t *conn = handle->conn;
280 SQLRowCount(conn->stmt, &c);
285 /* Exported to rlm_sql */
286 extern rlm_sql_module_t rlm_sql_db2;
287 rlm_sql_module_t rlm_sql_db2 = {
288 .name = "rlm_sql_db2",
289 .sql_socket_init = sql_socket_init,
290 .sql_query = sql_query,
291 .sql_select_query = sql_select_query,
292 .sql_num_fields = sql_num_fields,
293 .sql_affected_rows = sql_affected_rows,
294 .sql_fields = sql_fields,
295 .sql_fetch_row = sql_fetch_row,
296 .sql_free_result = sql_free_result,
297 .sql_error = sql_error,
298 .sql_finish_query = sql_finish_query,
299 .sql_finish_select_query = sql_finish_select_query