| 
									
										
										
										
											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
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-04-17 16:42:21 +00:00
										 |  |  |  * Copyright (C) 2004 - 2006, Digium, Inc. | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-26 08:05:36 +00:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * \file | 
					
						
							| 
									
										
										
										
											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
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-26 08:45:11 +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 , | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 	[uniqueid] [varchar] (32) NULL , | 
					
						
							|  |  |  | 	[userfield] [varchar] (256) NULL | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | ) ON [PRIMARY] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  | \endverbatim | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-24 17:11:45 +00:00
										 |  |  | /*** MODULEINFO
 | 
					
						
							|  |  |  | 	<depend>freetds</depend> | 
					
						
							| 
									
										
										
										
											2011-07-14 20:28:54 +00:00
										 |  |  | 	<support_level>extended</support_level> | 
					
						
							| 
									
										
										
										
											2006-04-24 17:11:45 +00:00
										 |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-06-06 21:09:59 +00:00
										 |  |  | #include "asterisk/config.h"
 | 
					
						
							|  |  |  | #include "asterisk/channel.h"
 | 
					
						
							|  |  |  | #include "asterisk/cdr.h"
 | 
					
						
							|  |  |  | #include "asterisk/module.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | #include <sqlfront.h>
 | 
					
						
							|  |  |  | #include <sybdb.h>
 | 
					
						
							| 
									
										
										
										
											2004-08-13 20:27:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | #define DATE_FORMAT "%Y/%m/%d %T"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-26 08:45:11 +00:00
										 |  |  | static const char name[] = "FreeTDS (MSSQL)"; | 
					
						
							|  |  |  | static const char config[] = "cdr_tds.conf"; | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | struct cdr_tds_config { | 
					
						
							|  |  |  | 	AST_DECLARE_STRING_FIELDS( | 
					
						
							|  |  |  | 		AST_STRING_FIELD(hostname); | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 		AST_STRING_FIELD(database); | 
					
						
							|  |  |  | 		AST_STRING_FIELD(username); | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 		AST_STRING_FIELD(password); | 
					
						
							|  |  |  | 		AST_STRING_FIELD(table); | 
					
						
							|  |  |  | 		AST_STRING_FIELD(charset); | 
					
						
							|  |  |  | 		AST_STRING_FIELD(language); | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | 		AST_STRING_FIELD(hrtime); | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 	); | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	DBPROCESS *dbproc; | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 	unsigned int connected:1; | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 	unsigned int has_userfield:1; | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | AST_MUTEX_DEFINE_STATIC(tds_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | static struct cdr_tds_config *settings; | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 21:16:41 +00:00
										 |  |  | static char *anti_injection(const char *, int); | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | static void get_date(char *, size_t len, struct timeval); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | static int execute_and_consume(DBPROCESS *dbproc, const char *fmt, ...) | 
					
						
							| 
									
										
										
										
											2008-11-29 17:57:39 +00:00
										 |  |  | 	__attribute__((format(printf, 2, 3))); | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	char start[80], answer[80], end[80]; | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 	char *accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid, *userfield = NULL; | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	RETCODE erc; | 
					
						
							|  |  |  | 	int res = -1; | 
					
						
							| 
									
										
										
										
											2008-08-14 15:03:03 +00:00
										 |  |  | 	int attempt = 1; | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	accountcode = anti_injection(cdr->accountcode, 20); | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	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); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	get_date(start, sizeof(start), cdr->start); | 
					
						
							|  |  |  | 	get_date(answer, sizeof(answer), cdr->answer); | 
					
						
							|  |  |  | 	get_date(end, sizeof(end), cdr->end); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&tds_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 	if (settings->has_userfield) { | 
					
						
							|  |  |  | 		userfield = anti_injection(cdr->userfield, AST_MAX_USER_FIELD); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-14 15:03:03 +00:00
										 |  |  | retry: | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	/* Ensure that we are connected */ | 
					
						
							|  |  |  | 	if (!settings->connected) { | 
					
						
							| 
									
										
										
										
											2008-08-14 15:03:03 +00:00
										 |  |  | 		ast_log(LOG_NOTICE, "Attempting to reconnect to %s (Attempt %d)\n", settings->hostname, attempt); | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 		if (mssql_connect()) { | 
					
						
							|  |  |  | 			/* Connect failed */ | 
					
						
							| 
									
										
										
										
											2008-08-14 15:03:03 +00:00
										 |  |  | 			if (attempt++ < 3) { | 
					
						
							|  |  |  | 				goto retry; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 			goto done; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 	if (settings->has_userfield) { | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | 		if (settings->hrtime) { | 
					
						
							|  |  |  | 			double hrbillsec = 0.0; | 
					
						
							|  |  |  | 			double hrduration; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (!ast_tvzero(cdr->answer)) { | 
					
						
							|  |  |  | 				hrbillsec = (double)(ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			hrduration = (double)(ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			erc = dbfcmd(settings->dbproc, | 
					
						
							|  |  |  | 					 "INSERT INTO %s " | 
					
						
							|  |  |  | 					 "(" | 
					
						
							|  |  |  | 					 "accountcode, src, dst, dcontext, clid, channel, " | 
					
						
							|  |  |  | 					 "dstchannel, lastapp, lastdata, start, answer, [end], duration, " | 
					
						
							|  |  |  | 					 "billsec, disposition, amaflags, uniqueid, userfield" | 
					
						
							|  |  |  | 					 ") " | 
					
						
							|  |  |  | 					 "VALUES " | 
					
						
							|  |  |  | 					 "(" | 
					
						
							|  |  |  | 					 "'%s', '%s', '%s', '%s', '%s', '%s', " | 
					
						
							|  |  |  | 					 "'%s', '%s', '%s', %s, %s, %s, %lf, " | 
					
						
							|  |  |  | 					 "%lf, '%s', '%s', '%s', '%s'" | 
					
						
							|  |  |  | 					 ")", | 
					
						
							|  |  |  | 					 settings->table, | 
					
						
							|  |  |  | 					 accountcode, src, dst, dcontext, clid, channel, | 
					
						
							|  |  |  | 					 dstchannel, lastapp, lastdata, start, answer, end, hrduration, | 
					
						
							| 
									
										
										
										
											2013-06-17 03:00:38 +00:00
										 |  |  | 					 hrbillsec, ast_cdr_disp2str(cdr->disposition), ast_channel_amaflags2string(cdr->amaflags), uniqueid, | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | 					 userfield | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			erc = dbfcmd(settings->dbproc, | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 					 "INSERT INTO %s " | 
					
						
							|  |  |  | 					 "(" | 
					
						
							|  |  |  | 					 "accountcode, src, dst, dcontext, clid, channel, " | 
					
						
							|  |  |  | 					 "dstchannel, lastapp, lastdata, start, answer, [end], duration, " | 
					
						
							|  |  |  | 					 "billsec, disposition, amaflags, uniqueid, userfield" | 
					
						
							|  |  |  | 					 ") " | 
					
						
							|  |  |  | 					 "VALUES " | 
					
						
							|  |  |  | 					 "(" | 
					
						
							|  |  |  | 					 "'%s', '%s', '%s', '%s', '%s', '%s', " | 
					
						
							|  |  |  | 					 "'%s', '%s', '%s', %s, %s, %s, %ld, " | 
					
						
							|  |  |  | 					 "%ld, '%s', '%s', '%s', '%s'" | 
					
						
							|  |  |  | 					 ")", | 
					
						
							|  |  |  | 					 settings->table, | 
					
						
							|  |  |  | 					 accountcode, src, dst, dcontext, clid, channel, | 
					
						
							|  |  |  | 					 dstchannel, lastapp, lastdata, start, answer, end, cdr->duration, | 
					
						
							| 
									
										
										
										
											2013-06-17 03:00:38 +00:00
										 |  |  | 					 cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_channel_amaflags2string(cdr->amaflags), uniqueid, | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 					 userfield | 
					
						
							|  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | 		if (settings->hrtime) { | 
					
						
							|  |  |  | 			double hrbillsec = 0.0; | 
					
						
							|  |  |  | 			double hrduration; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (!ast_tvzero(cdr->answer)) { | 
					
						
							|  |  |  | 				hrbillsec = (double)(ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			hrduration = (double)(ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			erc = dbfcmd(settings->dbproc, | 
					
						
							|  |  |  | 					 "INSERT INTO %s " | 
					
						
							|  |  |  | 					 "(" | 
					
						
							|  |  |  | 					 "accountcode, src, dst, dcontext, clid, channel, " | 
					
						
							|  |  |  | 					 "dstchannel, lastapp, lastdata, start, answer, [end], duration, " | 
					
						
							|  |  |  | 					 "billsec, disposition, amaflags, uniqueid" | 
					
						
							|  |  |  | 					 ") " | 
					
						
							|  |  |  | 					 "VALUES " | 
					
						
							|  |  |  | 					 "(" | 
					
						
							|  |  |  | 					 "'%s', '%s', '%s', '%s', '%s', '%s', " | 
					
						
							|  |  |  | 					 "'%s', '%s', '%s', %s, %s, %s, %lf, " | 
					
						
							|  |  |  | 					 "%lf, '%s', '%s', '%s'" | 
					
						
							|  |  |  | 					 ")", | 
					
						
							|  |  |  | 					 settings->table, | 
					
						
							|  |  |  | 					 accountcode, src, dst, dcontext, clid, channel, | 
					
						
							|  |  |  | 					 dstchannel, lastapp, lastdata, start, answer, end, hrduration, | 
					
						
							| 
									
										
										
										
											2013-06-17 03:00:38 +00:00
										 |  |  | 					 hrbillsec, ast_cdr_disp2str(cdr->disposition), ast_channel_amaflags2string(cdr->amaflags), uniqueid | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | 			); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			erc = dbfcmd(settings->dbproc, | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 					 "INSERT INTO %s " | 
					
						
							|  |  |  | 					 "(" | 
					
						
							|  |  |  | 					 "accountcode, src, dst, dcontext, clid, channel, " | 
					
						
							|  |  |  | 					 "dstchannel, lastapp, lastdata, start, answer, [end], duration, " | 
					
						
							|  |  |  | 					 "billsec, disposition, amaflags, uniqueid" | 
					
						
							|  |  |  | 					 ") " | 
					
						
							|  |  |  | 					 "VALUES " | 
					
						
							|  |  |  | 					 "(" | 
					
						
							|  |  |  | 					 "'%s', '%s', '%s', '%s', '%s', '%s', " | 
					
						
							|  |  |  | 					 "'%s', '%s', '%s', %s, %s, %s, %ld, " | 
					
						
							|  |  |  | 					 "%ld, '%s', '%s', '%s'" | 
					
						
							|  |  |  | 					 ")", | 
					
						
							|  |  |  | 					 settings->table, | 
					
						
							|  |  |  | 					 accountcode, src, dst, dcontext, clid, channel, | 
					
						
							|  |  |  | 					 dstchannel, lastapp, lastdata, start, answer, end, cdr->duration, | 
					
						
							| 
									
										
										
										
											2013-06-17 03:00:38 +00:00
										 |  |  | 					 cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_channel_amaflags2string(cdr->amaflags), uniqueid | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 			); | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	if (erc == FAIL) { | 
					
						
							| 
									
										
										
										
											2008-08-14 15:03:03 +00:00
										 |  |  | 		if (attempt++ < 3) { | 
					
						
							|  |  |  | 			ast_log(LOG_NOTICE, "Failed to build INSERT statement, retrying...\n"); | 
					
						
							|  |  |  | 			mssql_disconnect(); | 
					
						
							|  |  |  | 			goto retry; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Failed to build INSERT statement, no CDR was logged.\n"); | 
					
						
							|  |  |  | 			goto done; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (dbsqlexec(settings->dbproc) == FAIL) { | 
					
						
							| 
									
										
										
										
											2008-08-14 15:03:03 +00:00
										 |  |  | 		if (attempt++ < 3) { | 
					
						
							|  |  |  | 			ast_log(LOG_NOTICE, "Failed to execute INSERT statement, retrying...\n"); | 
					
						
							|  |  |  | 			mssql_disconnect(); | 
					
						
							|  |  |  | 			goto retry; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Failed to execute INSERT statement, no CDR was logged.\n"); | 
					
						
							|  |  |  | 			goto done; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	/* Consume any results we might get back (this is more of a sanity check than
 | 
					
						
							|  |  |  | 	 * anything else, since an INSERT shouldn't return results). */ | 
					
						
							|  |  |  | 	while (dbresults(settings->dbproc) != NO_MORE_RESULTS) { | 
					
						
							|  |  |  | 		while (dbnextrow(settings->dbproc) != NO_MORE_ROWS); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	res = 0; | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | done: | 
					
						
							|  |  |  | 	ast_mutex_unlock(&tds_lock); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 	ast_free(accountcode); | 
					
						
							|  |  |  | 	ast_free(src); | 
					
						
							|  |  |  | 	ast_free(dst); | 
					
						
							|  |  |  | 	ast_free(dcontext); | 
					
						
							|  |  |  | 	ast_free(clid); | 
					
						
							|  |  |  | 	ast_free(channel); | 
					
						
							|  |  |  | 	ast_free(dstchannel); | 
					
						
							|  |  |  | 	ast_free(lastapp); | 
					
						
							|  |  |  | 	ast_free(lastdata); | 
					
						
							|  |  |  | 	ast_free(uniqueid); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 	if (userfield) { | 
					
						
							|  |  |  | 		ast_free(userfield); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-02 14:30:09 +00:00
										 |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-16 15:25:03 +00:00
										 |  |  | 	if (!(buf = ast_calloc(1, len + 1))) { | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Out of memory\n"); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	buf_ptr = buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Escape single quotes */ | 
					
						
							| 
									
										
										
										
											2008-06-16 15:25:03 +00:00
										 |  |  | 	for (; *str && strlen(buf) < len; str++) { | 
					
						
							|  |  |  | 		if (*str == '\'') { | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 			*buf_ptr++ = '\''; | 
					
						
							| 
									
										
										
										
											2008-06-16 15:25:03 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 		*buf_ptr++ = *str; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	*buf_ptr = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Erase known bad input */ | 
					
						
							| 
									
										
										
										
											2008-06-16 15:25:03 +00:00
										 |  |  | 	for (idx = 0; *known_bad[idx]; idx++) { | 
					
						
							|  |  |  | 		while ((srh_ptr = strcasestr(buf, known_bad[idx]))) { | 
					
						
							|  |  |  | 			memmove(srh_ptr, srh_ptr + strlen(known_bad[idx]), strlen(srh_ptr + strlen(known_bad[idx])) + 1); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return buf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-07 00:52:23 +00:00
										 |  |  | static void get_date(char *dateField, size_t len, struct timeval when) | 
					
						
							| 
									
										
										
										
											2004-07-27 21:16:41 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* To make sure we have date variable if not insert null to SQL */ | 
					
						
							| 
									
										
										
										
											2008-08-07 15:10:53 +00:00
										 |  |  | 	if (!ast_tvzero(when)) { | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 		struct ast_tm tm; | 
					
						
							| 
									
										
										
										
											2008-08-07 00:52:23 +00:00
										 |  |  | 		ast_localtime(&when, &tm, NULL); | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 		ast_strftime(dateField, len, "'" DATE_FORMAT "'", &tm); | 
					
						
							| 
									
										
										
										
											2008-06-16 15:25:03 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 		ast_copy_string(dateField, "null", len); | 
					
						
							| 
									
										
										
										
											2004-07-27 21:16:41 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | static int execute_and_consume(DBPROCESS *dbproc, const char *fmt, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	va_list ap; | 
					
						
							|  |  |  | 	char *buffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	va_start(ap, fmt); | 
					
						
							| 
									
										
										
										
											2008-08-13 14:22:47 +00:00
										 |  |  | 	if (ast_vasprintf(&buffer, fmt, ap) < 0) { | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 		va_end(ap); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	va_end(ap); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (dbfcmd(dbproc, buffer) == FAIL) { | 
					
						
							| 
									
										
										
										
											2012-08-21 21:01:11 +00:00
										 |  |  | 		ast_free(buffer); | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-21 21:01:11 +00:00
										 |  |  | 	ast_free(buffer); | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (dbsqlexec(dbproc) == FAIL) { | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Consume the result set (we don't really care about the result, though) */ | 
					
						
							|  |  |  | 	while (dbresults(dbproc) != NO_MORE_RESULTS) { | 
					
						
							|  |  |  | 		while (dbnextrow(dbproc) != NO_MORE_ROWS); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | static int mssql_disconnect(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	if (settings->dbproc) { | 
					
						
							|  |  |  | 		dbclose(settings->dbproc); | 
					
						
							|  |  |  | 		settings->dbproc = NULL; | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 	settings->connected = 0; | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int mssql_connect(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	LOGINREC *login; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((login = dblogin()) == NULL) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Unable to allocate login structure for db-lib\n"); | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-06-16 15:25:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	DBSETLAPP(login,     "TSQL"); | 
					
						
							| 
									
										
										
										
											2008-06-30 11:57:42 +00:00
										 |  |  | 	DBSETLUSER(login,    (char *) settings->username); | 
					
						
							|  |  |  | 	DBSETLPWD(login,     (char *) settings->password); | 
					
						
							|  |  |  | 	DBSETLCHARSET(login, (char *) settings->charset); | 
					
						
							|  |  |  | 	DBSETLNATLANG(login, (char *) settings->language); | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if ((settings->dbproc = dbopen(login, (char *) settings->hostname)) == NULL) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Unable to connect to %s\n", settings->hostname); | 
					
						
							|  |  |  | 		dbloginfree(login); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	dbloginfree(login); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (dbuse(settings->dbproc, (char *) settings->database) == FAIL) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Unable to select database %s\n", settings->database); | 
					
						
							|  |  |  | 		goto failed; | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-08 15:39:52 +00:00
										 |  |  | 	if (execute_and_consume(settings->dbproc, "SELECT 1 FROM [%s] WHERE 1 = 0", settings->table)) { | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Unable to find table '%s'\n", settings->table); | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 		goto failed; | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 14:25:15 +00:00
										 |  |  | 	/* Check to see if we have a userfield column in the table */ | 
					
						
							|  |  |  | 	if (execute_and_consume(settings->dbproc, "SELECT userfield FROM [%s] WHERE 1 = 0", settings->table)) { | 
					
						
							|  |  |  | 		ast_log(LOG_NOTICE, "Unable to find 'userfield' column in table '%s'\n", settings->table); | 
					
						
							|  |  |  | 		settings->has_userfield = 0; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		settings->has_userfield = 1; | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 	settings->connected = 1; | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | failed: | 
					
						
							|  |  |  | 	dbclose(settings->dbproc); | 
					
						
							|  |  |  | 	settings->dbproc = NULL; | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | static int tds_unload_module(void) | 
					
						
							| 
									
										
										
										
											2008-06-16 17:33:10 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-10-27 20:04:17 +00:00
										 |  |  | 	if (ast_cdr_unregister(name)) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	if (settings) { | 
					
						
							|  |  |  | 		ast_mutex_lock(&tds_lock); | 
					
						
							|  |  |  | 		mssql_disconnect(); | 
					
						
							|  |  |  | 		ast_mutex_unlock(&tds_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-17 20:00:36 +00:00
										 |  |  | 		ast_string_field_free_memory(settings); | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 		ast_free(settings); | 
					
						
							| 
									
										
										
										
											2008-06-17 20:00:36 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	dbexit(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2008-06-16 17:33:10 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | static int tds_error_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr) | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	ast_log(LOG_ERROR, "%s (%d)\n", dberrstr, dberr); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	if (oserr != DBNOERR) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "%s (%d)\n", oserrstr, oserr); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	return INT_CANCEL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int tds_message_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ast_debug(1, "Msg %d, Level %d, State %d, Line %d\n", msgno, severity, msgstate, line); | 
					
						
							|  |  |  | 	ast_log(LOG_NOTICE, "%s\n", msgtext); | 
					
						
							| 
									
										
										
										
											2005-02-16 03:52:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | static int tds_load_module(int reload) | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct ast_config *cfg; | 
					
						
							| 
									
										
										
										
											2006-09-20 21:08:32 +00:00
										 |  |  | 	const char *ptr = NULL; | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	cfg = ast_config_load(config, config_flags); | 
					
						
							| 
									
										
										
										
											2008-11-19 19:25:14 +00:00
										 |  |  | 	if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) { | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 		ast_log(LOG_NOTICE, "Unable to load TDS config for CDRs: %s\n", config); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	} else if (cfg == CONFIG_STATUS_FILEUNCHANGED) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	if (!ast_variable_browse(cfg, "global")) { | 
					
						
							|  |  |  | 		/* nothing configured */ | 
					
						
							| 
									
										
										
										
											2007-11-07 22:09:10 +00:00
										 |  |  | 		ast_config_destroy(cfg); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2007-11-07 22:09:10 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-06-16 15:25:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	ast_mutex_lock(&tds_lock); | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	/* Clear out any existing settings */ | 
					
						
							|  |  |  | 	ast_string_field_init(settings, 0); | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-24 13:47:55 +00:00
										 |  |  | 	/* 'connection' is the new preferred configuration option */ | 
					
						
							|  |  |  | 	ptr = ast_variable_retrieve(cfg, "global", "connection"); | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	if (ptr) { | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 		ast_string_field_set(settings, hostname, ptr); | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2009-06-24 13:47:55 +00:00
										 |  |  | 		/* But we keep 'hostname' for backwards compatibility */ | 
					
						
							|  |  |  | 		ptr = ast_variable_retrieve(cfg, "global", "hostname"); | 
					
						
							|  |  |  | 		if (ptr) { | 
					
						
							|  |  |  | 			ast_string_field_set(settings, hostname, ptr); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Failed to connect: Database server connection not specified.\n"); | 
					
						
							|  |  |  | 			goto failed; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ptr = ast_variable_retrieve(cfg, "global", "dbname"); | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	if (ptr) { | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 		ast_string_field_set(settings, database, ptr); | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Failed to connect: Database dbname not specified.\n"); | 
					
						
							|  |  |  | 		goto failed; | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ptr = ast_variable_retrieve(cfg, "global", "user"); | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	if (ptr) { | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 		ast_string_field_set(settings, username, ptr); | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Failed to connect: Database dbuser not specified.\n"); | 
					
						
							|  |  |  | 		goto failed; | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ptr = ast_variable_retrieve(cfg, "global", "password"); | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	if (ptr) { | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 		ast_string_field_set(settings, password, ptr); | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Failed to connect: Database password not specified.\n"); | 
					
						
							|  |  |  | 		goto failed; | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ptr = ast_variable_retrieve(cfg, "global", "charset"); | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 	if (ptr) { | 
					
						
							|  |  |  | 		ast_string_field_set(settings, charset, ptr); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ast_string_field_set(settings, charset, "iso_1"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 	ptr = ast_variable_retrieve(cfg, "global", "language"); | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 	if (ptr) { | 
					
						
							|  |  |  | 		ast_string_field_set(settings, language, ptr); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ast_string_field_set(settings, language, "us_english"); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	ptr = ast_variable_retrieve(cfg, "global", "table"); | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 	if (ptr) { | 
					
						
							|  |  |  | 		ast_string_field_set(settings, table, ptr); | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		ast_log(LOG_NOTICE, "Table name not specified, using 'cdr' by default.\n"); | 
					
						
							| 
									
										
										
										
											2008-06-16 17:14:11 +00:00
										 |  |  | 		ast_string_field_set(settings, table, "cdr"); | 
					
						
							| 
									
										
										
										
											2006-03-08 22:12:20 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | 	ptr = ast_variable_retrieve(cfg, "global", "hrtime"); | 
					
						
							|  |  |  | 	if (ptr && ast_true(ptr)) { | 
					
						
							|  |  |  | 		ast_string_field_set(settings, hrtime, ptr); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ast_log(LOG_NOTICE, "High Resolution Time not found, using integers for billsec and duration fields by default.\n"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	mssql_disconnect(); | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (mssql_connect()) { | 
					
						
							|  |  |  | 		/* We failed to connect (mssql_connect takes care of logging it) */ | 
					
						
							|  |  |  | 		goto failed; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_unlock(&tds_lock); | 
					
						
							|  |  |  | 	ast_config_destroy(cfg); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-16 16:29:18 +00:00
										 |  |  | 	return 1; | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | failed: | 
					
						
							|  |  |  | 	ast_mutex_unlock(&tds_lock); | 
					
						
							|  |  |  | 	ast_config_destroy(cfg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int reload(void) | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	return tds_load_module(1); | 
					
						
							| 
									
										
										
										
											2005-04-07 14:53:17 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int load_module(void) | 
					
						
							| 
									
										
										
										
											2006-08-31 21:50:55 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	if (dbinit() == FAIL) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Failed to initialize FreeTDS db-lib\n"); | 
					
						
							| 
									
										
										
										
											2006-08-31 21:00:20 +00:00
										 |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dberrhandle(tds_error_handler); | 
					
						
							|  |  |  | 	dbmsghandle(tds_message_handler); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-15 18:21:50 +00:00
										 |  |  | 	settings = ast_calloc_with_stringfields(1, struct cdr_tds_config, 256); | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-15 18:21:50 +00:00
										 |  |  | 	if (!settings) { | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 		dbexit(); | 
					
						
							|  |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!tds_load_module(0)) { | 
					
						
							|  |  |  | 		ast_string_field_free_memory(settings); | 
					
						
							|  |  |  | 		ast_free(settings); | 
					
						
							|  |  |  | 		settings = NULL; | 
					
						
							|  |  |  | 		dbexit(); | 
					
						
							|  |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	ast_cdr_register(name, ast_module_info->description, tds_log); | 
					
						
							| 
									
										
										
										
											2008-06-28 21:28:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	return AST_MODULE_LOAD_SUCCESS; | 
					
						
							| 
									
										
										
										
											2005-04-07 14:53:17 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int unload_module(void) | 
					
						
							| 
									
										
										
										
											2005-04-07 14:53:17 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	return tds_unload_module(); | 
					
						
							| 
									
										
										
										
											2004-07-23 17:34:57 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-20 19:35:02 +00:00
										 |  |  | AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "FreeTDS CDR Backend", | 
					
						
							| 
									
										
										
										
											2015-05-04 23:57:57 -04:00
										 |  |  | 	.support_level = AST_MODULE_SUPPORT_EXTENDED, | 
					
						
							|  |  |  | 	.load = load_module, | 
					
						
							|  |  |  | 	.unload = unload_module, | 
					
						
							|  |  |  | 	.reload = reload, | 
					
						
							|  |  |  | 	.load_pri = AST_MODPRI_CDR_DRIVER, | 
					
						
							| 
									
										
										
										
											2018-02-16 22:11:42 -05:00
										 |  |  | 	.requires = "cdr", | 
					
						
							| 
									
										
										
										
											2015-05-04 23:57:57 -04:00
										 |  |  | ); |