diff --git a/cdr/cdr_tds.c b/cdr/cdr_tds.c index 7876d65063..6ac5c09c59 100644 --- a/cdr/cdr_tds.c +++ b/cdr/cdr_tds.c @@ -84,16 +84,24 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") static char *name = "mssql"; static char *config = "cdr_tds.conf"; -static char *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL, *charset = NULL, *language = NULL; -static char *table = NULL; +struct cdr_tds_config { + AST_DECLARE_STRING_FIELDS( + AST_STRING_FIELD(hostname); + AST_STRING_FIELD(dbname); + AST_STRING_FIELD(dbuser); + AST_STRING_FIELD(password); + AST_STRING_FIELD(table); + AST_STRING_FIELD(charset); + AST_STRING_FIELD(language); + ); + TDSSOCKET *tds; + TDSLOGIN *login; + TDSCONTEXT *context; + unsigned int connected:1; + ast_mutex_t lock; +}; -static int connected = 0; - -AST_MUTEX_DEFINE_STATIC(tds_lock); - -static TDSSOCKET *tds; -static TDSLOGIN *login; -static TDSCONTEXT *context; +static struct cdr_tds_config *settings; static char *anti_injection(const char *, int); static void get_date(char *, struct timeval); @@ -111,7 +119,7 @@ static int tds_log(struct ast_cdr *cdr) TDS_INT result_type; #endif - ast_mutex_lock(&tds_lock); + ast_mutex_lock(&settings->lock); memset(sqlcmd, 0, 2048); @@ -172,7 +180,7 @@ static int tds_log(struct ast_cdr *cdr) "'%s', " /* amaflags */ "'%s'" /* uniqueid */ ")", - table, + settings->table, accountcode, src, dst, @@ -193,7 +201,7 @@ static int tds_log(struct ast_cdr *cdr) ); do { - if (!connected) { + if (!settings->connected) { if (mssql_connect()) ast_log(LOG_ERROR, "Failed to reconnect to SQL database.\n"); else @@ -203,16 +211,16 @@ static int tds_log(struct ast_cdr *cdr) } #ifdef FREETDS_PRE_0_62 - if (!connected || (tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED)) + if (!settings->connected || (tds_submit_query(settings->tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(settings->tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED)) #else - if (!connected || (tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED)) + if (!settings->connected || (tds_submit_query(settings->tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(settings->tds) != TDS_SUCCEED)) #endif { ast_log(LOG_ERROR, "Failed to insert Call Data Record into SQL database.\n"); mssql_disconnect(); /* this is ok even if we are already disconnected */ } - } while (!connected && !retried); + } while (!settings->connected && !retried); ast_free(accountcode); ast_free(src); @@ -225,7 +233,7 @@ static int tds_log(struct ast_cdr *cdr) ast_free(lastdata); ast_free(uniqueid); - ast_mutex_unlock(&tds_lock); + ast_mutex_unlock(&settings->lock); return res; } @@ -233,14 +241,13 @@ static int tds_log(struct ast_cdr *cdr) static char *anti_injection(const char *str, int len) { /* 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 = ast_calloc(1, len + 1))) { - ast_log(LOG_ERROR, "cdr_tds: Out of memory error\n"); + ast_log(LOG_ERROR, "Out of memory\n"); return NULL; } @@ -282,22 +289,22 @@ static void get_date(char *dateField, struct timeval tv) static int mssql_disconnect(void) { - if (tds) { - tds_free_socket(tds); - tds = NULL; + if (settings->tds) { + tds_free_socket(settings->tds); + settings->tds = NULL; } - if (context) { - tds_free_context(context); - context = NULL; + if (settings->context) { + tds_free_context(settings->context); + settings->context = NULL; } - if (login) { - tds_free_login(login); - login = NULL; + if (settings->login) { + tds_free_login(settings->login); + settings->login = NULL; } - connected = 0; + settings->connected = 0; return 0; } @@ -312,48 +319,48 @@ static int mssql_connect(void) char query[128]; /* Connect to M$SQL Server */ - if (!(login = tds_alloc_login())) { + if (!(settings->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"); + tds_set_server(settings->login, settings->hostname); + tds_set_user(settings->login, settings->dbuser); + tds_set_passwd(settings->login, settings->password); + tds_set_app(settings->login, "TSQL"); + tds_set_library(settings->login, "TDS-Library"); #ifndef FREETDS_PRE_0_62 - tds_set_client_charset(login, charset); + tds_set_client_charset(settings->login, settings->charset); #endif - tds_set_language(login, language); - tds_set_packet(login, 512); - tds_set_version(login, 7, 0); + tds_set_language(settings->login, settings->language); + tds_set_packet(settings->login, 512); + tds_set_version(settings->login, 7, 0); #ifdef FREETDS_0_64 - if (!(context = tds_alloc_context(NULL))) + if (!(settings->context = tds_alloc_context(NULL))) #else - if (!(context = tds_alloc_context())) + if (!(settings->context = tds_alloc_context())) #endif { ast_log(LOG_ERROR, "tds_alloc_context() failed.\n"); goto connect_fail; } - if (!(tds = tds_alloc_socket(context, 512))) { + if (!(settings->tds = tds_alloc_socket(settings->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); + tds_set_parent(settings->tds, NULL); + connection = tds_read_config_info(settings->tds, settings->login, settings->context->locale); if (!connection) { ast_log(LOG_ERROR, "tds_read_config() failed.\n"); goto connect_fail; } - if (tds_connect(tds, connection) == TDS_FAIL) { + if (tds_connect(settings->tds, connection) == TDS_FAIL) { ast_log(LOG_ERROR, "Failed to connect to MSSQL server.\n"); - tds = NULL; /* freed by tds_connect() on error */ + settings->tds = NULL; /* freed by tds_connect() on error */ #if (defined(FREETDS_0_63) || defined(FREETDS_0_64)) tds_free_connection(connection); #else @@ -369,18 +376,18 @@ static int mssql_connect(void) #endif connection = NULL; - sprintf(query, "USE %s", dbname); + sprintf(query, "USE %s", settings->dbname); #ifdef FREETDS_PRE_0_62 - if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED)) + if ((tds_submit_query(settings->tds, query) != TDS_SUCCEED) || (tds_process_simple_query(settings->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)) + if ((tds_submit_query(settings->tds, query) != TDS_SUCCEED) || (tds_process_simple_query(settings->tds) != TDS_SUCCEED)) #endif { - ast_log(LOG_ERROR, "Could not change database (%s)\n", dbname); + ast_log(LOG_ERROR, "Could not change database (%s)\n", settings->dbname); goto connect_fail; } - connected = 1; + settings->connected = 1; return 0; connect_fail: @@ -394,13 +401,9 @@ static int tds_unload_module(void) ast_cdr_unregister(name); - if (hostname) ast_free(hostname); - if (dbname) ast_free(dbname); - if (dbuser) ast_free(dbuser); - if (password) ast_free(password); - if (charset) ast_free(charset); - if (language) ast_free(language); - if (table) ast_free(table); + ast_mutex_destroy(&settings->lock); + ast_string_field_free_memory(settings); + ast_free(settings); return 0; } @@ -425,69 +428,79 @@ static int tds_load_module(int reload) return 0; } + if (reload) { + ast_string_field_init(settings, 0); + } else { + settings = ast_calloc(1, sizeof(*settings)); + + if (!settings || ast_string_field_init(settings, 256)) { + if (settings) { + ast_free(settings); + settings = NULL; + } + ast_config_destroy(cfg); + return 0; + } + } + + ast_mutex_init(&settings->lock); + ptr = ast_variable_retrieve(cfg, "global", "hostname"); if (ptr) { - if (hostname) - ast_free(hostname); - hostname = ast_strdup(ptr); - } else + ast_string_field_set(settings, hostname, ptr); + } else { ast_log(LOG_ERROR, "Database server hostname not specified.\n"); + } ptr = ast_variable_retrieve(cfg, "global", "dbname"); if (ptr) { - if (dbname) - ast_free(dbname); - dbname = ast_strdup(ptr); - } else + ast_string_field_set(settings, dbname, ptr); + } else { ast_log(LOG_ERROR, "Database dbname not specified.\n"); + } ptr = ast_variable_retrieve(cfg, "global", "user"); if (ptr) { - if (dbuser) - ast_free(dbuser); - dbuser = ast_strdup(ptr); - } else + ast_string_field_set(settings, dbuser, ptr); + } else { ast_log(LOG_ERROR, "Database dbuser not specified.\n"); + } ptr = ast_variable_retrieve(cfg, "global", "password"); if (ptr) { - if (password) - ast_free(password); - password = ast_strdup(ptr); - } else + ast_string_field_set(settings, password, ptr); + } else { ast_log(LOG_ERROR,"Database password not specified.\n"); + } ptr = ast_variable_retrieve(cfg, "global", "charset"); - if (charset) - ast_free(charset); - if (ptr) - charset = ast_strdup(ptr); - else - charset = ast_strdup("iso_1"); + if (ptr) { + ast_string_field_set(settings, charset, ptr); + } else { + ast_string_field_set(settings, charset, "iso_1"); + } - if (language) - ast_free(language); ptr = ast_variable_retrieve(cfg, "global", "language"); - if (ptr) - language = ast_strdup(ptr); - else - language = ast_strdup("us_english"); + if (ptr) { + ast_string_field_set(settings, language, ptr); + } else { + ast_string_field_set(settings, language, "us_english"); + } ptr = ast_variable_retrieve(cfg, "global", "table"); - if (ptr == NULL) { - ast_debug(1, "cdr_tds: table not specified. Assuming cdr\n"); - ptr = "cdr"; + if (ptr) { + ast_string_field_set(settings, table, ptr); + } else { + ast_debug(1, "Table not specified. Assuming 'cdr'\n"); + ast_string_field_set(settings, table, "cdr"); } - if (table) - ast_free(table); - table = ast_strdup(ptr); ast_config_destroy(cfg); - ast_mutex_lock(&tds_lock); + ast_mutex_lock(&settings->lock); mssql_disconnect(); mssql_connect(); - ast_mutex_unlock(&tds_lock); + ast_mutex_unlock(&settings->lock); return 1; }