⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sql_sybase.c

📁 RADIUS认证协议
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * sql_sybase.c	Sybase (ctlibrary) routines for rlm_sql *		Error handling stolen from Sybase example code "firstapp.c" * *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Copyright 2000  The FreeRADIUS server project * Copyright 2000  Mattias Sjostrom <mattias@nogui.se> */#include <stdio.h>#include <sys/stat.h>#include <stdlib.h>#include <string.h>#include 	"radiusd.h"#include <ctpublic.h>#include "rlm_sql.h"typedef struct rlm_sql_sybase_sock {	CS_CONTEXT	*context;	CS_CONNECTION	*connection;	CS_COMMAND	*command;	char		**results;	int		id;	int		in_use;	struct timeval	tv;} rlm_sql_sybase_sock;#define	MAX_DATASTR_LEN	256/************************************************************************* Handler for server messages. Client-Library will call this* routine when it receives a message from the server.************************************************************************/static CS_RETCODE CS_PUBLICservermsg_callback(cp, chp, msgp)CS_CONTEXT         *cp;CS_CONNECTION      *chp;CS_SERVERMSG       *msgp;{        /*        ** Print the message info.        */        radlog(L_ERR,                "Sybase Server message:\n");        radlog(L_ERR,                "number(%ld) severity(%ld) state(%ld) line(%ld)\n",                (long)msgp->msgnumber, (long)msgp->severity,                (long)msgp->state, (long)msgp->line);        /*        ** Print the server and procedure names if supplied.        */        if (msgp->svrnlen > 0 && msgp->proclen > 0)                radlog(L_ERR, "Server name: %s   Procedure name: %s", msgp->svrname, msgp->proc);        /*        ** Print the null terminated message.        */        radlog(L_ERR, "%s\n", msgp->text);        /*        ** Server message callbacks must return CS_SUCCEED.        */        return (CS_SUCCEED);}/*************************************************************************  Client-Library error handler.************************************************************************/static CS_RETCODE CS_PUBLICclientmsg_callback(context, conn, emsgp)CS_CONTEXT         *context;CS_CONNECTION      *conn;CS_CLIENTMSG       *emsgp;{        /*        ** Error number: Print the error's severity, number, origin, and        ** layer. These four numbers uniquely identify the error.        */        radlog(L_ERR,                "Client Library error:\n");        radlog(L_ERR,                "severity(%ld) number(%ld) origin(%ld) layer(%ld)\n",                (long)CS_SEVERITY(emsgp->severity),                (long)CS_NUMBER(emsgp->msgnumber),                (long)CS_ORIGIN(emsgp->msgnumber),                (long)CS_LAYER(emsgp->msgnumber));        /*        ** Error text: Print the error text.        */        radlog(L_ERR, "%s\n", emsgp->msgstring);        if (emsgp->osstringlen > 0)        {                radlog(L_ERR,                        "Operating system error number(%ld):\n",                        (long)emsgp->osnumber);                radlog(L_ERR, "%s\n", emsgp->osstring);        }        return (CS_SUCCEED);}/*************************************************************************  CS-Library error handler. This function will be invoked*  when CS-Library has detected an error.************************************************************************/static CS_RETCODE CS_PUBLICcsmsg_callback(context, emsgp)CS_CONTEXT         *context;CS_CLIENTMSG       *emsgp;{        /*        ** Print the error number and message.        */        radlog(L_ERR,                "CS-Library error:\n");        radlog(L_ERR,                "\tseverity(%ld) layer(%ld) origin(%ld) number(%ld)",                (long)CS_SEVERITY(emsgp->msgnumber),                (long)CS_LAYER(emsgp->msgnumber),                (long)CS_ORIGIN(emsgp->msgnumber),                (long)CS_NUMBER(emsgp->msgnumber));        radlog(L_ERR, "%s\n", emsgp->msgstring);        /*        ** Print any operating system error information.        */        if (emsgp->osstringlen > 0)        {                radlog(L_ERR, "Operating System Error: %s\n",                        emsgp->osstring);        }        return (CS_SUCCEED);}/************************************************************************* * *	Function: sql_init_socket * *	Purpose: Establish connection to the db * *************************************************************************/static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config) {	rlm_sql_sybase_sock *sybase_sock;	if (!sqlsocket->conn) {		sqlsocket->conn = (rlm_sql_sybase_sock *)rad_malloc(sizeof(rlm_sql_sybase_sock));		if (!sqlsocket->conn) {			return -1;		}	}	sybase_sock = sqlsocket->conn;	memset(sybase_sock, 0, sizeof(*sybase_sock));	sybase_sock->results=NULL;	/* Allocate a CS context structure. This should really only be done once, but because of	   the connection pooling design of rlm_sql, we'll have to go with one context per connection */	if (cs_ctx_alloc(CS_VERSION_100, &sybase_sock->context) != CS_SUCCEED) {		radlog(L_ERR,"rlm_sql_sybase(sql_init_socket): Unable to allocate CS context structure (cs_ctx_alloc())");		return -1;	}	/* Initialize ctlib */	if (ct_init(sybase_sock->context, CS_VERSION_100) != CS_SUCCEED) {		radlog(L_ERR,"rlm_sql_sybase(sql_init_socket): Unable to initialize Client-Library (ct_init())");		if (sybase_sock->context != (CS_CONTEXT *)NULL) {			cs_ctx_drop(sybase_sock->context);		}		return -1;	}	/* Install callback functions for error-handling */        if (cs_config(sybase_sock->context, CS_SET, CS_MESSAGE_CB, (CS_VOID *)csmsg_callback, CS_UNUSED, NULL) != CS_SUCCEED) {		radlog(L_ERR,"rlm_sql_sybase(sql_init_socket): Unable to install CS Library error callback");                if (sybase_sock->context != (CS_CONTEXT *)NULL) {                        ct_exit(sybase_sock->context, CS_FORCE_EXIT);                        cs_ctx_drop(sybase_sock->context);                }		return -1;	}	if (ct_callback(sybase_sock->context, NULL, CS_SET, CS_CLIENTMSG_CB, (CS_VOID *)clientmsg_callback) != CS_SUCCEED) {		radlog(L_ERR,"rlm_sql_sybase(sql_init_socket): Unable to install client message callback");                if (sybase_sock->context != (CS_CONTEXT *)NULL) {                        ct_exit(sybase_sock->context, CS_FORCE_EXIT);                        cs_ctx_drop(sybase_sock->context);                }		return -1;	}	if (ct_callback(sybase_sock->context, NULL, CS_SET, CS_SERVERMSG_CB, (CS_VOID *)servermsg_callback) != CS_SUCCEED) {		radlog(L_ERR,"rlm_sql_sybase(sql_init_socket): Unable to install client message callback");                if (sybase_sock->context != (CS_CONTEXT *)NULL) {                        ct_exit(sybase_sock->context, CS_FORCE_EXIT);                        cs_ctx_drop(sybase_sock->context);                }		return -1;	}	/* Allocate a ctlib connection structure */	if (ct_con_alloc(sybase_sock->context, &sybase_sock->connection) != CS_SUCCEED) {		radlog(L_ERR,"rlm_sql_sybase(sql_init_socket): Unable to allocate connection structure (ct_con_alloc())");		if (sybase_sock->context != (CS_CONTEXT *)NULL) {			ct_exit(sybase_sock->context, CS_FORCE_EXIT);			cs_ctx_drop(sybase_sock->context);		}		return -1;	}	/* Initialize inline error handling for the connection *//*	if (ct_diag(sybase_sock->connection, CS_INIT, CS_UNUSED, CS_UNUSED, NULL) != CS_SUCCEED) {		radlog(L_ERR,"rlm_sql_sybase(sql_init_socket): Unable to initialize error handling (ct_diag())");                if (sybase_sock->context != (CS_CONTEXT *)NULL) {                        ct_exit(sybase_sock->context, CS_FORCE_EXIT);                        cs_ctx_drop(sybase_sock->context);                }		return -1;	} */	/* Set User and Password properties for the connection */	if (ct_con_props(sybase_sock->connection, CS_SET, CS_USERNAME, config->sql_login,					 strlen(config->sql_login), NULL) != CS_SUCCEED) {		radlog(L_ERR,"rlm_sql_sybase(sql_init_socket): Unable to set username for connection (ct_con_props())\n%s",		sql_error(sqlsocket, config));		if (sybase_sock->context != (CS_CONTEXT *)NULL) {			ct_exit(sybase_sock->context, CS_FORCE_EXIT);			cs_ctx_drop(sybase_sock->context);		}		return -1;	}	if (ct_con_props(sybase_sock->connection, CS_SET, CS_PASSWORD, config->sql_password,					strlen(config->sql_password), NULL) != CS_SUCCEED) {		radlog(L_ERR,"rlm_sql_sybase(sql_init_socket): Unable to set password for connection (ct_con_props())\n%s",		sql_error(sqlsocket, config));		if (sybase_sock->context != (CS_CONTEXT *)NULL) {			ct_exit(sybase_sock->context, CS_FORCE_EXIT);			cs_ctx_drop(sybase_sock->context);		}		return -1;	}	/* Establish the connection */	if (ct_connect(sybase_sock->connection, config->sql_server, strlen(config->sql_server)) != CS_SUCCEED) {		radlog(L_ERR,"rlm_sql_sybase(sql_init_socket): Unable to establish connection to symbolic servername %s\n%s",				config->sql_server, sql_error(sqlsocket, config));		if (sybase_sock->context != (CS_CONTEXT *)NULL) {			ct_exit(sybase_sock->context, CS_FORCE_EXIT);			cs_ctx_drop(sybase_sock->context);		}		return -1;	}	return 0;}/************************************************************************* * *	Function: sql_destroy_socket * *	Purpose: Free socket and private connection data * *************************************************************************/static int sql_destroy_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config){	free(sqlsocket->conn);	sqlsocket->conn = NULL;	return 0;}/************************************************************************* * *	Function: sql_query * *	Purpose: Issue a non-SELECT query (ie: update/delete/insert) to *               the database. * *************************************************************************/static int sql_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querystr) {	rlm_sql_sybase_sock *sybase_sock = sqlsocket->conn;	CS_RETCODE	ret, results_ret;	CS_INT		result_type;	if (config->sqltrace)		DEBUG(querystr);	 if (sybase_sock->connection == NULL) {		radlog(L_ERR, "Socket not connected");		return -1;	}	if (ct_cmd_alloc(sybase_sock->connection, &sybase_sock->command) != CS_SUCCEED) {		radlog(L_ERR,"rlm_sql_sybase(sql_query): Unable to allocate command structure (ct_cmd_alloc())\n%s",				sql_error(sqlsocket, config));		return -1;	}	if (ct_command(sybase_sock->command, CS_LANG_CMD, querystr, CS_NULLTERM, CS_UNUSED) != CS_SUCCEED) {		radlog(L_ERR,"rlm_sql_sybase(sql_query): Unable to initiate command structure (ct_command())\n%s",				sql_error(sqlsocket, config));		return -1;	}	if (ct_send(sybase_sock->command) != CS_SUCCEED) {		radlog(L_ERR,"rlm_sql_sybase(sql_query): Unable to send command (ct_send())\n%s",				sql_error(sqlsocket, config));		return -1;	}	/*	** We'll make three calls to ct_results, first to get a success indicator, secondly to get a done indicator, and	** thirdly to get a "nothing left to handle" status.	*/	/*	** First call to ct_results,	** we need returncode CS_SUCCEED	** and result_type CS_CMD_SUCCEED.	*/	if ((results_ret = ct_results(sybase_sock->command, &result_type)) == CS_SUCCEED) {		if (result_type != CS_CMD_SUCCEED) {			if  (result_type == CS_ROW_RESULT) {				radlog(L_ERR,"rlm_sql_sybase(sql_query): sql_query processed a query returning rows. Use sql_select_query instead!");			}			radlog(L_ERR,"rlm_sql_sybase(sql_query): Result failure or unexpected result type from query\n%s",					 sql_error(sqlsocket, config));			return -1;		}	}	else {		switch ((int) results_ret)		{		case CS_FAIL: /* Serious failure, sybase requires us to cancel and maybe even close connection */			radlog(L_ERR,"rlm_sql_sybase(sql_query): Failure retrieving query results\n%s"					, sql_error(sqlsocket, config));			if ((ret = ct_cancel(NULL, sybase_sock->command, CS_CANCEL_ALL)) == CS_FAIL) {				radlog(L_ERR,"rlm_sql_sybase(sql_query): cleaning up.");				ct_close(sybase_sock->connection, CS_FORCE_CLOSE);				sql_close(sqlsocket, config);			}			return -1;			break;		default:			radlog(L_ERR,"rlm_sql_sybase(sql_query): Unexpected return value from ct_results()\n%s",					sql_error(sqlsocket, config));			return -1;		}	}	/*	** Second call to ct_results,	** we need returncode CS_SUCCEED	** and result_type CS_CMD_DONE.	*/	if ((results_ret = ct_results(sybase_sock->command, &result_type)) == CS_SUCCEED) {		if (result_type != CS_CMD_DONE) {			radlog(L_ERR,"rlm_sql_sybase(sql_query): Result failure or unexpected result type from query\n%s",					 sql_error(sqlsocket, config));			return -1;		}	}	else {		switch ((int) results_ret)		{		case CS_FAIL: /* Serious failure, sybase requires us to cancel and maybe even close connection */			radlog(L_ERR,"rlm_sql_sybase(sql_query): Failure retrieving query results\n%s"					, sql_error(sqlsocket, config));			if ((ret = ct_cancel(NULL, sybase_sock->command, CS_CANCEL_ALL)) == CS_FAIL) {				radlog(L_ERR,"rlm_sql_sybase(sql_query): cleaning up.");				ct_close(sybase_sock->connection, CS_FORCE_CLOSE);				sql_close(sqlsocket, config);			}			return -1;			break;		default:			radlog(L_ERR,"rlm_sql_sybase(sql_query): Unexpected return value from ct_results()\n%s",					sql_error(sqlsocket, config));			return -1;		}	}	/*	** Third call to ct_results,	** we need returncode CS_END_RESULTS	** result_type will be ignored.	*/	results_ret = ct_results(sybase_sock->command, &result_type);	switch ((int) results_ret)	{	case CS_FAIL: /* Serious failure, sybase requires us to cancel and maybe even close connection */		radlog(L_ERR,"rlm_sql_sybase(sql_query): Failure retrieving query results\n%s"				, sql_error(sqlsocket, config));		if ((ret = ct_cancel(NULL, sybase_sock->command, CS_CANCEL_ALL)) == CS_FAIL) {			radlog(L_ERR,"rlm_sql_sybase(sql_query): cleaning up.");			ct_close(sybase_sock->connection, CS_FORCE_CLOSE);			sql_close(sqlsocket, config);		}		return -1;		break;	case CS_END_RESULTS:  /* This is where we want to end up */		break;	default:		radlog(L_ERR,"rlm_sql_sybase(sql_query): Unexpected return value from ct_results()\n%s",				sql_error(sqlsocket, config));		return -1;		break;	}	return 0;}/************************************************************************* * *	Function: sql_select_query * *	Purpose: Issue a select query to the database * *	Note: Only the first row from queries returning several rows *	      will be returned by this function, consequitive rows will *	      be discarded. * *************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -