diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 14:11:00 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 14:11:00 +0000 |
commit | af754e596a8dbb05ed8580c342e7fe02e08b28e0 (patch) | |
tree | b2f334c2b55ede42081aa6710a72da784547d8ea /src/modules/rlm_sql/drivers/rlm_sql_db2/rlm_sql_db2.c | |
parent | Initial commit. (diff) | |
download | freeradius-b95e0cd7685e6bbc2465b1f4efe1884df2f4ef01.tar.xz freeradius-b95e0cd7685e6bbc2465b1f4efe1884df2f4ef01.zip |
Adding upstream version 3.2.3+dfsg.upstream/3.2.3+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/modules/rlm_sql/drivers/rlm_sql_db2/rlm_sql_db2.c')
-rw-r--r-- | src/modules/rlm_sql/drivers/rlm_sql_db2/rlm_sql_db2.c | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/src/modules/rlm_sql/drivers/rlm_sql_db2/rlm_sql_db2.c b/src/modules/rlm_sql/drivers/rlm_sql_db2/rlm_sql_db2.c new file mode 100644 index 0000000..01d1710 --- /dev/null +++ b/src/modules/rlm_sql/drivers/rlm_sql_db2/rlm_sql_db2.c @@ -0,0 +1,271 @@ +/* + * sql_db2.c IBM DB2 rlm_sql driver + * + * Version: $Id$ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * Copyright 2000,2006 The FreeRADIUS server project + * Copyright 2000 Mike Machado <mike@innercite.com> + * Copyright 2000 Alan DeKok <aland@ox.org> + * Copyright 2001 Joerg Wendland <wendland@scan-plus.de> + */ + +/* + * Modification of rlm_sql_db2 to handle IBM DB2 UDB V7 + * by Joerg Wendland <wendland@scan-plus.de> + */ + +RCSID("$Id$") + +#include <freeradius-devel/radiusd.h> +#include <freeradius-devel/rad_assert.h> + +#include <sys/stat.h> + +#include <sqlcli.h> + +#include "rlm_sql.h" + +typedef struct rlm_sql_conn { + SQLHANDLE dbc_handle; + SQLHANDLE env_handle; + SQLHANDLE stmt; +} rlm_sql_db2_conn_t; + +static int _sql_socket_destructor(rlm_sql_db2_conn_t *conn) +{ + DEBUG2("rlm_sql_db2: Socket destructor called, closing socket"); + + if (conn->stmt) { + SQLFreeHandle(SQL_HANDLE_STMT, conn->stmt); + conn->stmt = 0; + } + + if (conn->dbc_handle) { + SQLDisconnect(conn->dbc_handle); + SQLFreeHandle(SQL_HANDLE_DBC, conn->dbc_handle); + conn->dbc_handle = 0; + } + + if (conn->env_handle) { + SQLFreeHandle(SQL_HANDLE_ENV, conn->env_handle); + conn->env_handle = 0; + } + + return RLM_SQL_OK; +} + +static sql_rcode_t sql_socket_init(rlm_sql_handle_t *handle, rlm_sql_config_t *config) +{ + SQLRETURN retval; + rlm_sql_db2_conn_t *conn; + + MEM(conn = handle->conn = talloc_zero(handle, rlm_sql_db2_conn_t)); + talloc_set_destructor(conn, _sql_socket_destructor); + + /* Allocate handles */ + SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(conn->env_handle)); + SQLAllocHandle(SQL_HANDLE_DBC, conn->env_handle, &(conn->dbc_handle)); + + /* + * The db2 API doesn't qualify arguments as const even when they should be. + */ + { + SQLCHAR *server, *login, *password; + + memcpy(&server, &config->sql_server, sizeof(server)); + memcpy(&login, &config->sql_login, sizeof(login)); + memcpy(&password, &config->sql_password, sizeof(password)); + + retval = SQLConnect(conn->dbc_handle, + server, SQL_NTS, + login, SQL_NTS, + password, SQL_NTS); + } + + if (retval != SQL_SUCCESS) { + ERROR("could not connect to DB2 server %s", config->sql_server); + + return RLM_SQL_ERROR; + } + + return RLM_SQL_OK; +} + +static sql_rcode_t sql_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config, char const *query) +{ + SQLRETURN retval; + rlm_sql_db2_conn_t *conn; + + conn = handle->conn; + + /* allocate handle for statement */ + SQLAllocHandle(SQL_HANDLE_STMT, conn->dbc_handle, &(conn->stmt)); + + /* execute query */ + { + SQLCHAR *db2_query; + memcpy(&db2_query, &query, sizeof(query)); + + retval = SQLExecDirect(conn->stmt, db2_query, SQL_NTS); + if (retval != SQL_SUCCESS) { + SQLFreeHandle(SQL_HANDLE_STMT, conn->stmt); + conn->stmt = 0; + + /* XXX Check if retval means we should return RLM_SQL_RECONNECT */ + ERROR("Could not execute statement \"%s\"", query); + return RLM_SQL_ERROR; + } + } + + return RLM_SQL_OK; +} + +static sql_rcode_t sql_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config, char const *query) +{ + return sql_query(handle, config, query); +} + +static int sql_num_fields(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config) +{ + SQLSMALLINT c; + rlm_sql_db2_conn_t *conn; + + conn = handle->conn; + SQLNumResultCols(conn->stmt, &c); + return c; +} + +static sql_rcode_t sql_fetch_row(rlm_sql_handle_t *handle, rlm_sql_config_t *config) +{ + int c, i; + SQLINTEGER len, slen; + rlm_sql_row_t retval; + rlm_sql_db2_conn_t *conn; + + conn = handle->conn; + + c = sql_num_fields(handle, config); + retval = (rlm_sql_row_t)rad_malloc(c*sizeof(char*)+1); + memset(retval, 0, c*sizeof(char*)+1); + + /* advance cursor */ + if (SQLFetch(conn->stmt) == SQL_NO_DATA_FOUND) { + handle->row = NULL; + for (i = 0; i < c; i++) free(retval[i]); + free(retval); + return RLM_SQL_NO_MORE_ROWS; + } + + for (i = 0; i < c; i++) { + /* get column length */ + SQLColAttribute(conn->stmt, i+1, SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL, &len); + + retval[i] = rad_malloc(len+1); + + /* get the actual column */ + SQLGetData(conn->stmt, i + 1, SQL_C_CHAR, retval[i], len+1, &slen); + if(slen == SQL_NULL_DATA) { + retval[i][0] = '\0'; + } + } + + handle->row = retval; + return RLM_SQL_OK; +} + +static sql_rcode_t sql_free_result(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config) +{ + rlm_sql_db2_conn_t *conn; + conn = handle->conn; + + if (conn->stmt) { + SQLFreeHandle(SQL_HANDLE_STMT, conn->stmt); + conn->stmt = 0; + } + + return RLM_SQL_OK; +} + +/** Retrieves any errors associated with the connection handle + * + * @note Caller will free any memory allocated in ctx. + * + * @param ctx to allocate temporary error buffers in. + * @param out Array of sql_log_entrys to fill. + * @param outlen Length of out array. + * @param handle rlm_sql connection handle. + * @param config rlm_sql config. + * @return number of errors written to the sql_log_entry array. + */ +static size_t sql_error(TALLOC_CTX *ctx, sql_log_entry_t out[], size_t outlen, + rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config) +{ + char state[6]; + char errbuff[1024]; + SQLINTEGER err; + SQLSMALLINT rl; + rlm_sql_db2_conn_t *conn = handle->conn; + + rad_assert(conn); + rad_assert(outlen > 0); + + errbuff[0] = '\0'; + SQLGetDiagRec(SQL_HANDLE_STMT, conn->stmt, 1, (SQLCHAR *) state, &err, + (SQLCHAR *) errbuff, sizeof(errbuff), &rl); + if (errbuff[0] == '\0') return 0; + + out[0].type = L_ERR; + out[0].msg = talloc_asprintf(ctx, "%s: %s", state, errbuff); + + return 1; +} + +static sql_rcode_t sql_finish_query(UNUSED rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config) +{ + return RLM_SQL_OK; +} + +static sql_rcode_t sql_finish_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config) +{ + return sql_finish_query(handle, config); +} + +static int sql_affected_rows(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config) +{ + SQLINTEGER c; + rlm_sql_db2_conn_t *conn = handle->conn; + + SQLRowCount(conn->stmt, &c); + + return c; +} + +/* Exported to rlm_sql */ +extern rlm_sql_module_t rlm_sql_db2; +rlm_sql_module_t rlm_sql_db2 = { + .name = "rlm_sql_db2", + .sql_socket_init = sql_socket_init, + .sql_query = sql_query, + .sql_select_query = sql_select_query, + .sql_num_fields = sql_num_fields, + .sql_affected_rows = sql_affected_rows, + .sql_fetch_row = sql_fetch_row, + .sql_free_result = sql_free_result, + .sql_error = sql_error, + .sql_finish_query = sql_finish_query, + .sql_finish_select_query = sql_finish_select_query +}; |