| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * Copyright (C) 2004 - 2005, Digium, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is free software, distributed under the terms of | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  | /*! \file
 | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  |  * \brief FreeTDS CDR logger | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  |  * See also | 
					
						
							|  |  |  |  * \arg \ref Config_cdr | 
					
						
							|  |  |  |  * \arg http://www.freetds.org/
 | 
					
						
							| 
									
										
										
										
											2005-11-06 15:09:47 +00:00
										 |  |  |  * \ingroup cdr_drivers | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \verbatim
 | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Table Structure for `cdr` | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Created on: 05/20/2004 16:16 | 
					
						
							| 
									
										
										
										
											2004-07-27 21:16:41 +00:00
										 |  |  |  * Last changed on: 07/27/2004 20:01 | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | CREATE TABLE [dbo].[cdr] ( | 
					
						
							|  |  |  | 	[accountcode] [varchar] (20) NULL , | 
					
						
							|  |  |  | 	[src] [varchar] (80) NULL , | 
					
						
							|  |  |  | 	[dst] [varchar] (80) NULL , | 
					
						
							|  |  |  | 	[dcontext] [varchar] (80) NULL , | 
					
						
							|  |  |  | 	[clid] [varchar] (80) NULL , | 
					
						
							|  |  |  | 	[channel] [varchar] (80) NULL , | 
					
						
							|  |  |  | 	[dstchannel] [varchar] (80) NULL , | 
					
						
							|  |  |  | 	[lastapp] [varchar] (80) NULL , | 
					
						
							|  |  |  | 	[lastdata] [varchar] (80) NULL , | 
					
						
							|  |  |  | 	[start] [datetime] NULL , | 
					
						
							|  |  |  | 	[answer] [datetime] NULL , | 
					
						
							|  |  |  | 	[end] [datetime] NULL , | 
					
						
							|  |  |  | 	[duration] [int] NULL , | 
					
						
							|  |  |  | 	[billsec] [int] NULL , | 
					
						
							|  |  |  | 	[disposition] [varchar] (20) NULL , | 
					
						
							|  |  |  | 	[amaflags] [varchar] (16) NULL , | 
					
						
							|  |  |  | 	[uniqueid] [varchar] (32) NULL | 
					
						
							|  |  |  | ) ON [PRIMARY] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  | \endverbatim | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <time.h>
 | 
					
						
							|  |  |  | #include <math.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <tds.h>
 | 
					
						
							|  |  |  | #include <tdsconvert.h>
 | 
					
						
							|  |  |  | #include <ctype.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-06-06 21:09:59 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-06-06 23:12:05 +00:00
										 |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | 
					
						
							| 
									
										
										
										
											2005-06-06 21:09:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "asterisk/config.h"
 | 
					
						
							|  |  |  | #include "asterisk/options.h"
 | 
					
						
							|  |  |  | #include "asterisk/channel.h"
 | 
					
						
							|  |  |  | #include "asterisk/cdr.h"
 | 
					
						
							|  |  |  | #include "asterisk/module.h"
 | 
					
						
							|  |  |  | #include "asterisk/logger.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-29 18:49:25 +00:00
										 |  |  | #ifdef FREETDS_PRE_0_62
 | 
					
						
							| 
									
										
										
										
											2004-08-13 20:27:58 +00:00
										 |  |  | #warning "You have older TDS, you should upgrade!"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | #define DATE_FORMAT "%Y/%m/%d %T"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *desc = "MSSQL CDR Backend"; | 
					
						
							|  |  |  | static char *name = "mssql"; | 
					
						
							|  |  |  | static char *config = "cdr_tds.conf"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | static char *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL, *charset = NULL, *language = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int connected = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | AST_MUTEX_DEFINE_STATIC(tds_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static TDSSOCKET *tds; | 
					
						
							|  |  |  | static TDSLOGIN *login; | 
					
						
							|  |  |  | static TDSCONTEXT *context; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 21:16:41 +00:00
										 |  |  | static char *anti_injection(const char *, int); | 
					
						
							|  |  |  | static void get_date(char *, struct timeval); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | static int mssql_connect(void); | 
					
						
							|  |  |  | static int mssql_disconnect(void); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | static int tds_log(struct ast_cdr *cdr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char sqlcmd[2048], start[80], answer[80], end[80]; | 
					
						
							|  |  |  | 	char *accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid; | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	int retried = 0; | 
					
						
							| 
									
										
										
										
											2005-10-29 18:49:25 +00:00
										 |  |  | #ifdef FREETDS_PRE_0_62
 | 
					
						
							| 
									
										
										
										
											2004-08-13 20:27:58 +00:00
										 |  |  | 	TDS_INT result_type; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&tds_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memset(sqlcmd, 0, 2048); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	accountcode = anti_injection(cdr->accountcode, 20); | 
					
						
							|  |  |  | 	src = anti_injection(cdr->src, 80); | 
					
						
							|  |  |  | 	dst = anti_injection(cdr->dst, 80); | 
					
						
							|  |  |  | 	dcontext = anti_injection(cdr->dcontext, 80); | 
					
						
							|  |  |  | 	clid = anti_injection(cdr->clid, 80); | 
					
						
							|  |  |  | 	channel = anti_injection(cdr->channel, 80); | 
					
						
							|  |  |  | 	dstchannel = anti_injection(cdr->dstchannel, 80); | 
					
						
							|  |  |  | 	lastapp = anti_injection(cdr->lastapp, 80); | 
					
						
							|  |  |  | 	lastdata = anti_injection(cdr->lastdata, 80); | 
					
						
							|  |  |  | 	uniqueid = anti_injection(cdr->uniqueid, 32); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 21:16:41 +00:00
										 |  |  | 	get_date(start, cdr->start); | 
					
						
							|  |  |  | 	get_date(answer, cdr->answer); | 
					
						
							|  |  |  | 	get_date(end, cdr->end); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sprintf( | 
					
						
							|  |  |  | 		sqlcmd, | 
					
						
							|  |  |  | 		"INSERT INTO cdr " | 
					
						
							|  |  |  | 		"(" | 
					
						
							|  |  |  | 			"accountcode, " | 
					
						
							|  |  |  | 			"src, " | 
					
						
							|  |  |  | 			"dst, " | 
					
						
							|  |  |  | 			"dcontext, " | 
					
						
							|  |  |  | 			"clid, " | 
					
						
							|  |  |  | 			"channel, " | 
					
						
							|  |  |  | 			"dstchannel, " | 
					
						
							|  |  |  | 			"lastapp, " | 
					
						
							|  |  |  | 			"lastdata, " | 
					
						
							|  |  |  | 			"start, " | 
					
						
							|  |  |  | 			"answer, " | 
					
						
							|  |  |  | 			"[end], " | 
					
						
							|  |  |  | 			"duration, " | 
					
						
							|  |  |  | 			"billsec, " | 
					
						
							|  |  |  | 			"disposition, " | 
					
						
							|  |  |  | 			"amaflags, " | 
					
						
							|  |  |  | 			"uniqueid" | 
					
						
							|  |  |  | 		") " | 
					
						
							|  |  |  | 		"VALUES " | 
					
						
							|  |  |  | 		"(" | 
					
						
							|  |  |  | 			"'%s', "	/* accountcode */ | 
					
						
							|  |  |  | 			"'%s', "	/* src */ | 
					
						
							|  |  |  | 			"'%s', "	/* dst */ | 
					
						
							|  |  |  | 			"'%s', "	/* dcontext */ | 
					
						
							|  |  |  | 			"'%s', "	/* clid */ | 
					
						
							|  |  |  | 			"'%s', "	/* channel */ | 
					
						
							|  |  |  | 			"'%s', "	/* dstchannel */ | 
					
						
							|  |  |  | 			"'%s', "	/* lastapp */ | 
					
						
							|  |  |  | 			"'%s', "	/* lastdata */ | 
					
						
							|  |  |  | 			"%s, "		/* start */ | 
					
						
							|  |  |  | 			"%s, "		/* answer */ | 
					
						
							|  |  |  | 			"%s, "		/* end */ | 
					
						
							| 
									
										
										
										
											2005-04-29 17:00:33 +00:00
										 |  |  | 			"%d, "		/* duration */ | 
					
						
							|  |  |  | 			"%d, "		/* billsec */ | 
					
						
							| 
									
										
										
										
											2004-07-27 21:16:41 +00:00
										 |  |  | 			"'%s', "	/* disposition */ | 
					
						
							|  |  |  | 			"'%s', "	/* amaflags */ | 
					
						
							|  |  |  | 			"'%s'"		/* uniqueid */ | 
					
						
							|  |  |  | 		")", | 
					
						
							|  |  |  | 		accountcode, | 
					
						
							|  |  |  | 		src, | 
					
						
							|  |  |  | 		dst, | 
					
						
							|  |  |  | 		dcontext, | 
					
						
							|  |  |  | 		clid, | 
					
						
							|  |  |  | 		channel, | 
					
						
							|  |  |  | 		dstchannel, | 
					
						
							|  |  |  | 		lastapp, | 
					
						
							|  |  |  | 		lastdata, | 
					
						
							|  |  |  | 		start, | 
					
						
							|  |  |  | 		answer, | 
					
						
							|  |  |  | 		end, | 
					
						
							|  |  |  | 		cdr->duration, | 
					
						
							|  |  |  | 		cdr->billsec, | 
					
						
							|  |  |  | 		ast_cdr_disp2str(cdr->disposition), | 
					
						
							|  |  |  | 		ast_cdr_flags2str(cdr->amaflags), | 
					
						
							|  |  |  | 		uniqueid | 
					
						
							|  |  |  | 	); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	do { | 
					
						
							|  |  |  | 		if (!connected) { | 
					
						
							|  |  |  | 			if (mssql_connect()) | 
					
						
							|  |  |  | 				ast_log(LOG_ERROR, "Failed to reconnect to SQL database.\n"); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				ast_log(LOG_WARNING, "Reconnected to SQL database.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			retried = 1;	/* note that we have now tried */ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-29 18:49:25 +00:00
										 |  |  | #ifdef FREETDS_PRE_0_62
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		if (!connected || (tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED)) | 
					
						
							| 
									
										
										
										
											2004-08-13 20:27:58 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		if (!connected || (tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED)) | 
					
						
							| 
									
										
										
										
											2004-08-13 20:27:58 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Failed to insert Call Data Record into SQL database.\n"); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 			mssql_disconnect();	/* this is ok even if we are already disconnected */ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} while (!connected && !retried); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	free(accountcode); | 
					
						
							|  |  |  | 	free(src); | 
					
						
							|  |  |  | 	free(dst); | 
					
						
							|  |  |  | 	free(dcontext); | 
					
						
							|  |  |  | 	free(clid); | 
					
						
							|  |  |  | 	free(channel); | 
					
						
							|  |  |  | 	free(dstchannel); | 
					
						
							|  |  |  | 	free(lastapp); | 
					
						
							|  |  |  | 	free(lastdata); | 
					
						
							|  |  |  | 	free(uniqueid); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_unlock(&tds_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 21:16:41 +00:00
										 |  |  | static char *anti_injection(const char *str, int len) | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* Reference to http://www.nextgenss.com/papers/advanced_sql_injection.pdf */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	char *buf; | 
					
						
							|  |  |  | 	char *buf_ptr, *srh_ptr; | 
					
						
							|  |  |  | 	char *known_bad[] = {"select", "insert", "update", "delete", "drop", ";", "--", "\0"}; | 
					
						
							|  |  |  | 	int idx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((buf = malloc(len + 1)) == NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "cdr_tds:  Out of memory error\n"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	memset(buf, 0, len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	buf_ptr = buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Escape single quotes */ | 
					
						
							|  |  |  | 	for (; *str && strlen(buf) < len; str++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (*str == '\'') | 
					
						
							|  |  |  | 			*buf_ptr++ = '\''; | 
					
						
							|  |  |  | 		*buf_ptr++ = *str; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	*buf_ptr = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Erase known bad input */ | 
					
						
							|  |  |  | 	for (idx=0; *known_bad[idx]; idx++) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2005-12-26 20:32:50 +00:00
										 |  |  | 		while((srh_ptr = strcasestr(buf, known_bad[idx]))) | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			memmove(srh_ptr, srh_ptr+strlen(known_bad[idx]), strlen(srh_ptr+strlen(known_bad[idx]))+1); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return buf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 21:16:41 +00:00
										 |  |  | static void get_date(char *dateField, struct timeval tv) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct tm tm; | 
					
						
							|  |  |  | 	time_t t; | 
					
						
							|  |  |  | 	char buf[80]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* To make sure we have date variable if not insert null to SQL */ | 
					
						
							| 
									
										
										
										
											2005-07-15 23:00:47 +00:00
										 |  |  | 	if (!ast_tvzero(tv)) | 
					
						
							| 
									
										
										
										
											2004-07-27 21:16:41 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		t = tv.tv_sec; | 
					
						
							|  |  |  | 		localtime_r(&t, &tm); | 
					
						
							|  |  |  | 		strftime(buf, 80, DATE_FORMAT, &tm); | 
					
						
							|  |  |  | 		sprintf(dateField, "'%s'", buf); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		strcpy(dateField, "null"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | char *description(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return desc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | static int mssql_disconnect(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (tds) { | 
					
						
							|  |  |  | 		tds_free_socket(tds); | 
					
						
							|  |  |  | 		tds = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (context) { | 
					
						
							|  |  |  | 		tds_free_context(context); | 
					
						
							|  |  |  | 		context = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (login) { | 
					
						
							|  |  |  | 		tds_free_login(login); | 
					
						
							|  |  |  | 		login = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	connected = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int mssql_connect(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-29 18:49:25 +00:00
										 |  |  | #ifdef FREETDS_0_63
 | 
					
						
							|  |  |  | 	TDSCONNECTION *connection = NULL; | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	TDSCONNECTINFO *connection = NULL; | 
					
						
							| 
									
										
										
										
											2005-10-29 18:49:25 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	char query[128]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Connect to M$SQL Server */ | 
					
						
							|  |  |  | 	if (!(login = tds_alloc_login())) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "tds_alloc_login() failed.\n"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	tds_set_server(login, hostname); | 
					
						
							|  |  |  | 	tds_set_user(login, dbuser); | 
					
						
							|  |  |  | 	tds_set_passwd(login, password); | 
					
						
							|  |  |  | 	tds_set_app(login, "TSQL"); | 
					
						
							|  |  |  | 	tds_set_library(login, "TDS-Library"); | 
					
						
							| 
									
										
										
										
											2005-10-29 18:49:25 +00:00
										 |  |  | #ifndef FREETDS_PRE_0_62
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	tds_set_client_charset(login, charset); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	tds_set_language(login, language); | 
					
						
							|  |  |  | 	tds_set_packet(login, 512); | 
					
						
							|  |  |  | 	tds_set_version(login, 7, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(context = tds_alloc_context())) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "tds_alloc_context() failed.\n"); | 
					
						
							|  |  |  | 		goto connect_fail; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(tds = tds_alloc_socket(context, 512))) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "tds_alloc_socket() failed.\n"); | 
					
						
							|  |  |  | 		goto connect_fail; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tds_set_parent(tds, NULL); | 
					
						
							|  |  |  | 	connection = tds_read_config_info(tds, login, context->locale); | 
					
						
							|  |  |  | 	if (!connection) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "tds_read_config() failed.\n"); | 
					
						
							|  |  |  | 		goto connect_fail; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (tds_connect(tds, connection) == TDS_FAIL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Failed to connect to MSSQL server.\n"); | 
					
						
							|  |  |  | 		tds = NULL;	/* freed by tds_connect() on error */ | 
					
						
							| 
									
										
										
										
											2005-10-29 18:49:25 +00:00
										 |  |  | #ifdef FREETDS_0_63
 | 
					
						
							|  |  |  | 		tds_free_connection(connection); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		tds_free_connect(connection); | 
					
						
							| 
									
										
										
										
											2005-10-29 18:49:25 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		connection = NULL; | 
					
						
							|  |  |  | 		goto connect_fail; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-29 18:49:25 +00:00
										 |  |  | #ifdef FREETDS_0_63
 | 
					
						
							|  |  |  | 	tds_free_connection(connection); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	tds_free_connect(connection); | 
					
						
							| 
									
										
										
										
											2005-10-29 18:49:25 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	connection = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sprintf(query, "USE %s", dbname); | 
					
						
							| 
									
										
										
										
											2005-10-29 18:49:25 +00:00
										 |  |  | #ifdef FREETDS_PRE_0_62
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED)) | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED)) | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Could not change database (%s)\n", dbname); | 
					
						
							|  |  |  | 		goto connect_fail; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	connected = 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | connect_fail: | 
					
						
							|  |  |  | 	mssql_disconnect(); | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-07 14:53:17 +00:00
										 |  |  | static int tds_unload_module(void) | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	mssql_disconnect(); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_cdr_unregister(name); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	if (hostname) free(hostname); | 
					
						
							|  |  |  | 	if (dbname) free(dbname); | 
					
						
							|  |  |  | 	if (dbuser) free(dbuser); | 
					
						
							|  |  |  | 	if (password) free(password); | 
					
						
							|  |  |  | 	if (charset) free(charset); | 
					
						
							|  |  |  | 	if (language) free(language); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-07 14:53:17 +00:00
										 |  |  | static int tds_load_module(void) | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 	struct ast_config *cfg; | 
					
						
							|  |  |  | 	struct ast_variable *var; | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	char *ptr = NULL; | 
					
						
							| 
									
										
										
										
											2005-10-29 18:49:25 +00:00
										 |  |  | #ifdef FREETDS_PRE_0_62
 | 
					
						
							| 
									
										
										
										
											2004-08-13 20:27:58 +00:00
										 |  |  | 	TDS_INT result_type; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-25 06:10:20 +00:00
										 |  |  | 	cfg = ast_config_load(config); | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	if (!cfg) { | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 		ast_log(LOG_NOTICE, "Unable to load config for MSSQL CDR's: %s\n", config); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var = ast_variable_browse(cfg, "global"); | 
					
						
							|  |  |  | 	if (!var) /* nothing configured */ | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ptr = ast_variable_retrieve(cfg, "global", "hostname"); | 
					
						
							|  |  |  | 	if (ptr) | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		hostname = strdup(ptr); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR,"Database server hostname not specified.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ptr = ast_variable_retrieve(cfg, "global", "dbname"); | 
					
						
							|  |  |  | 	if (ptr) | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		dbname = strdup(ptr); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR,"Database dbname not specified.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ptr = ast_variable_retrieve(cfg, "global", "user"); | 
					
						
							|  |  |  | 	if (ptr) | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		dbuser = strdup(ptr); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR,"Database dbuser not specified.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ptr = ast_variable_retrieve(cfg, "global", "password"); | 
					
						
							|  |  |  | 	if (ptr) | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		password = strdup(ptr); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR,"Database password not specified.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ptr = ast_variable_retrieve(cfg, "global", "charset"); | 
					
						
							|  |  |  | 	if (ptr) | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		charset = strdup(ptr); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		charset = strdup("iso_1"); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ptr = ast_variable_retrieve(cfg, "global", "language"); | 
					
						
							|  |  |  | 	if (ptr) | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		language = strdup(ptr); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		language = strdup("us_english"); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-25 06:10:20 +00:00
										 |  |  | 	ast_config_destroy(cfg); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	mssql_connect(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Register MSSQL CDR handler */ | 
					
						
							|  |  |  | 	res = ast_cdr_register(name, desc, tds_log); | 
					
						
							|  |  |  | 	if (res) | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Unable to register MSSQL CDR handling\n"); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int reload(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-07 14:53:17 +00:00
										 |  |  | 	tds_unload_module(); | 
					
						
							|  |  |  | 	return tds_load_module(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int load_module(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return tds_load_module(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int unload_module(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return tds_unload_module(); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int usecount(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	/* Simplistic use count */ | 
					
						
							|  |  |  | 	if (ast_mutex_trylock(&tds_lock)) { | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ast_mutex_unlock(&tds_lock); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char *key() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return ASTERISK_GPL_KEY; | 
					
						
							|  |  |  | } |