#include "asterisk.h"
#include "asterisk/config.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/module.h"
#include <sqlfront.h>
#include <sybdb.h>
Go to the source code of this file.
Data Structures | |
struct | cdr_tds_config |
Defines | |
#define | DATE_FORMAT "%Y/%m/%d %T" |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static char * | anti_injection (const char *, int) |
static int | execute_and_consume (DBPROCESS *dbproc, const char *fmt,...) |
static void | get_date (char *, size_t len, struct timeval) |
static int | load_module (void) |
static int | mssql_connect (void) |
static int | mssql_disconnect (void) |
static int | reload (void) |
static int | tds_error_handler (DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr) |
static int | tds_load_module (int reload) |
static int | tds_log (struct ast_cdr *cdr) |
static int | tds_message_handler (DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line) |
static int | tds_unload_module (void) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "FreeTDS CDR Backend" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static const char | config [] = "cdr_tds.conf" |
static const char | name [] = "FreeTDS (MSSQL)" |
static struct cdr_tds_config * | settings |
static ast_mutex_t | tds_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
See also
Definition in file cdr_tds.c.
#define DATE_FORMAT "%Y/%m/%d %T" |
* * Table Structure for `cdr` * * Created on: 05/20/2004 16:16 * Last changed on: 07/27/2004 20:01 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 , [userfield] [varchar] (256) NULL ) ON [PRIMARY]
static char * anti_injection | ( | const char * | , | |
int | ||||
) | [static] |
Definition at line 304 of file cdr_tds.c.
References ast_calloc, ast_log(), LOG_ERROR, and strcasestr().
Referenced by tds_log().
00305 { 00306 /* Reference to http://www.nextgenss.com/papers/advanced_sql_injection.pdf */ 00307 char *buf; 00308 char *buf_ptr, *srh_ptr; 00309 char *known_bad[] = {"select", "insert", "update", "delete", "drop", ";", "--", "\0"}; 00310 int idx; 00311 00312 if (!(buf = ast_calloc(1, len + 1))) { 00313 ast_log(LOG_ERROR, "Out of memory\n"); 00314 return NULL; 00315 } 00316 00317 buf_ptr = buf; 00318 00319 /* Escape single quotes */ 00320 for (; *str && strlen(buf) < len; str++) { 00321 if (*str == '\'') { 00322 *buf_ptr++ = '\''; 00323 } 00324 *buf_ptr++ = *str; 00325 } 00326 *buf_ptr = '\0'; 00327 00328 /* Erase known bad input */ 00329 for (idx = 0; *known_bad[idx]; idx++) { 00330 while ((srh_ptr = strcasestr(buf, known_bad[idx]))) { 00331 memmove(srh_ptr, srh_ptr + strlen(known_bad[idx]), strlen(srh_ptr + strlen(known_bad[idx])) + 1); 00332 } 00333 } 00334 00335 return buf; 00336 }
static int execute_and_consume | ( | DBPROCESS * | dbproc, | |
const char * | fmt, | |||
... | ||||
) | [static] |
Definition at line 350 of file cdr_tds.c.
References ast_vasprintf, and free.
Referenced by mssql_connect().
00351 { 00352 va_list ap; 00353 char *buffer; 00354 00355 va_start(ap, fmt); 00356 if (ast_vasprintf(&buffer, fmt, ap) < 0) { 00357 va_end(ap); 00358 return 1; 00359 } 00360 va_end(ap); 00361 00362 if (dbfcmd(dbproc, buffer) == FAIL) { 00363 free(buffer); 00364 return 1; 00365 } 00366 00367 free(buffer); 00368 00369 if (dbsqlexec(dbproc) == FAIL) { 00370 return 1; 00371 } 00372 00373 /* Consume the result set (we don't really care about the result, though) */ 00374 while (dbresults(dbproc) != NO_MORE_RESULTS) { 00375 while (dbnextrow(dbproc) != NO_MORE_ROWS); 00376 } 00377 00378 return 0; 00379 }
static void get_date | ( | char * | , | |
size_t | len, | |||
struct | timeval | |||
) | [static] |
Definition at line 338 of file cdr_tds.c.
References ast_copy_string(), ast_localtime(), ast_strftime(), ast_tvzero(), and DATE_FORMAT.
00339 { 00340 /* To make sure we have date variable if not insert null to SQL */ 00341 if (!ast_tvzero(when)) { 00342 struct ast_tm tm; 00343 ast_localtime(&when, &tm, NULL); 00344 ast_strftime(dateField, len, "'" DATE_FORMAT "'", &tm); 00345 } else { 00346 ast_copy_string(dateField, "null", len); 00347 } 00348 }
static int load_module | ( | void | ) | [static] |
Definition at line 597 of file cdr_tds.c.
References ast_calloc_with_stringfields, ast_cdr_register(), ast_free, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_string_field_free_memory, dbinit(), LOG_ERROR, settings, tds_error_handler(), tds_load_module(), tds_log(), and tds_message_handler().
00598 { 00599 if (dbinit() == FAIL) { 00600 ast_log(LOG_ERROR, "Failed to initialize FreeTDS db-lib\n"); 00601 return AST_MODULE_LOAD_DECLINE; 00602 } 00603 00604 dberrhandle(tds_error_handler); 00605 dbmsghandle(tds_message_handler); 00606 00607 settings = ast_calloc_with_stringfields(1, struct cdr_tds_config, 256); 00608 00609 if (!settings) { 00610 dbexit(); 00611 return AST_MODULE_LOAD_DECLINE; 00612 } 00613 00614 if (!tds_load_module(0)) { 00615 ast_string_field_free_memory(settings); 00616 ast_free(settings); 00617 settings = NULL; 00618 dbexit(); 00619 return AST_MODULE_LOAD_DECLINE; 00620 } 00621 00622 ast_cdr_register(name, ast_module_info->description, tds_log); 00623 00624 return AST_MODULE_LOAD_SUCCESS; 00625 }
static int mssql_connect | ( | void | ) | [static] |
Definition at line 393 of file cdr_tds.c.
References ast_log(), cdr_tds_config::charset, cdr_tds_config::connected, cdr_tds_config::database, cdr_tds_config::dbproc, execute_and_consume(), cdr_tds_config::has_userfield, cdr_tds_config::hostname, cdr_tds_config::language, LOG_ERROR, LOG_NOTICE, cdr_tds_config::password, settings, cdr_tds_config::table, and cdr_tds_config::username.
Referenced by tds_load_module(), and tds_log().
00394 { 00395 LOGINREC *login; 00396 00397 if ((login = dblogin()) == NULL) { 00398 ast_log(LOG_ERROR, "Unable to allocate login structure for db-lib\n"); 00399 return -1; 00400 } 00401 00402 DBSETLAPP(login, "TSQL"); 00403 DBSETLUSER(login, (char *) settings->username); 00404 DBSETLPWD(login, (char *) settings->password); 00405 DBSETLCHARSET(login, (char *) settings->charset); 00406 DBSETLNATLANG(login, (char *) settings->language); 00407 00408 if ((settings->dbproc = dbopen(login, (char *) settings->hostname)) == NULL) { 00409 ast_log(LOG_ERROR, "Unable to connect to %s\n", settings->hostname); 00410 dbloginfree(login); 00411 return -1; 00412 } 00413 00414 dbloginfree(login); 00415 00416 if (dbuse(settings->dbproc, (char *) settings->database) == FAIL) { 00417 ast_log(LOG_ERROR, "Unable to select database %s\n", settings->database); 00418 goto failed; 00419 } 00420 00421 if (execute_and_consume(settings->dbproc, "SELECT 1 FROM [%s] WHERE 1 = 0", settings->table)) { 00422 ast_log(LOG_ERROR, "Unable to find table '%s'\n", settings->table); 00423 goto failed; 00424 } 00425 00426 /* Check to see if we have a userfield column in the table */ 00427 if (execute_and_consume(settings->dbproc, "SELECT userfield FROM [%s] WHERE 1 = 0", settings->table)) { 00428 ast_log(LOG_NOTICE, "Unable to find 'userfield' column in table '%s'\n", settings->table); 00429 settings->has_userfield = 0; 00430 } else { 00431 settings->has_userfield = 1; 00432 } 00433 00434 settings->connected = 1; 00435 00436 return 0; 00437 00438 failed: 00439 dbclose(settings->dbproc); 00440 settings->dbproc = NULL; 00441 return -1; 00442 }
static int mssql_disconnect | ( | void | ) | [static] |
Definition at line 381 of file cdr_tds.c.
References cdr_tds_config::connected, cdr_tds_config::dbproc, and settings.
Referenced by tds_load_module(), tds_log(), and tds_unload_module().
00382 { 00383 if (settings->dbproc) { 00384 dbclose(settings->dbproc); 00385 settings->dbproc = NULL; 00386 } 00387 00388 settings->connected = 0; 00389 00390 return 0; 00391 }
static int reload | ( | void | ) | [static] |
Definition at line 592 of file cdr_tds.c.
References tds_load_module().
00593 { 00594 return tds_load_module(1); 00595 }
static int tds_error_handler | ( | DBPROCESS * | dbproc, | |
int | severity, | |||
int | dberr, | |||
int | oserr, | |||
char * | dberrstr, | |||
char * | oserrstr | |||
) | [static] |
Definition at line 462 of file cdr_tds.c.
References ast_log(), and LOG_ERROR.
Referenced by load_module().
00463 { 00464 ast_log(LOG_ERROR, "%s (%d)\n", dberrstr, dberr); 00465 00466 if (oserr != DBNOERR) { 00467 ast_log(LOG_ERROR, "%s (%d)\n", oserrstr, oserr); 00468 } 00469 00470 return INT_CANCEL; 00471 }
static int tds_load_module | ( | int | reload | ) | [static] |
Definition at line 481 of file cdr_tds.c.
References ast_config_destroy(), ast_config_load, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_string_field_init, ast_string_field_set, ast_true(), ast_variable_browse(), ast_variable_retrieve(), charset, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, hostname, language, LOG_ERROR, LOG_NOTICE, mssql_connect(), mssql_disconnect(), settings, table, and tds_lock.
Referenced by load_module(), and reload().
00482 { 00483 struct ast_config *cfg; 00484 const char *ptr = NULL; 00485 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 00486 00487 cfg = ast_config_load(config, config_flags); 00488 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) { 00489 ast_log(LOG_NOTICE, "Unable to load TDS config for CDRs: %s\n", config); 00490 return 0; 00491 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) 00492 return 0; 00493 00494 if (!ast_variable_browse(cfg, "global")) { 00495 /* nothing configured */ 00496 ast_config_destroy(cfg); 00497 return 0; 00498 } 00499 00500 ast_mutex_lock(&tds_lock); 00501 00502 /* Clear out any existing settings */ 00503 ast_string_field_init(settings, 0); 00504 00505 /* 'connection' is the new preferred configuration option */ 00506 ptr = ast_variable_retrieve(cfg, "global", "connection"); 00507 if (ptr) { 00508 ast_string_field_set(settings, hostname, ptr); 00509 } else { 00510 /* But we keep 'hostname' for backwards compatibility */ 00511 ptr = ast_variable_retrieve(cfg, "global", "hostname"); 00512 if (ptr) { 00513 ast_string_field_set(settings, hostname, ptr); 00514 } else { 00515 ast_log(LOG_ERROR, "Failed to connect: Database server connection not specified.\n"); 00516 goto failed; 00517 } 00518 } 00519 00520 ptr = ast_variable_retrieve(cfg, "global", "dbname"); 00521 if (ptr) { 00522 ast_string_field_set(settings, database, ptr); 00523 } else { 00524 ast_log(LOG_ERROR, "Failed to connect: Database dbname not specified.\n"); 00525 goto failed; 00526 } 00527 00528 ptr = ast_variable_retrieve(cfg, "global", "user"); 00529 if (ptr) { 00530 ast_string_field_set(settings, username, ptr); 00531 } else { 00532 ast_log(LOG_ERROR, "Failed to connect: Database dbuser not specified.\n"); 00533 goto failed; 00534 } 00535 00536 ptr = ast_variable_retrieve(cfg, "global", "password"); 00537 if (ptr) { 00538 ast_string_field_set(settings, password, ptr); 00539 } else { 00540 ast_log(LOG_ERROR, "Failed to connect: Database password not specified.\n"); 00541 goto failed; 00542 } 00543 00544 ptr = ast_variable_retrieve(cfg, "global", "charset"); 00545 if (ptr) { 00546 ast_string_field_set(settings, charset, ptr); 00547 } else { 00548 ast_string_field_set(settings, charset, "iso_1"); 00549 } 00550 00551 ptr = ast_variable_retrieve(cfg, "global", "language"); 00552 if (ptr) { 00553 ast_string_field_set(settings, language, ptr); 00554 } else { 00555 ast_string_field_set(settings, language, "us_english"); 00556 } 00557 00558 ptr = ast_variable_retrieve(cfg, "global", "table"); 00559 if (ptr) { 00560 ast_string_field_set(settings, table, ptr); 00561 } else { 00562 ast_log(LOG_NOTICE, "Table name not specified, using 'cdr' by default.\n"); 00563 ast_string_field_set(settings, table, "cdr"); 00564 } 00565 00566 ptr = ast_variable_retrieve(cfg, "global", "hrtime"); 00567 if (ptr && ast_true(ptr)) { 00568 ast_string_field_set(settings, hrtime, ptr); 00569 } else { 00570 ast_log(LOG_NOTICE, "High Resolution Time not found, using integers for billsec and duration fields by default.\n"); 00571 } 00572 00573 mssql_disconnect(); 00574 00575 if (mssql_connect()) { 00576 /* We failed to connect (mssql_connect takes care of logging it) */ 00577 goto failed; 00578 } 00579 00580 ast_mutex_unlock(&tds_lock); 00581 ast_config_destroy(cfg); 00582 00583 return 1; 00584 00585 failed: 00586 ast_mutex_unlock(&tds_lock); 00587 ast_config_destroy(cfg); 00588 00589 return 0; 00590 }
static int tds_log | ( | struct ast_cdr * | cdr | ) | [static] |
Definition at line 111 of file cdr_tds.c.
References accountcode, anti_injection(), ast_cdr_disp2str(), ast_cdr_flags2str(), ast_free, ast_log(), AST_MAX_USER_FIELD, ast_mutex_lock, ast_mutex_unlock, ast_tvdiff_us(), ast_tvzero(), cdr_tds_config::connected, cdr_tds_config::dbproc, get_date(), cdr_tds_config::has_userfield, cdr_tds_config::hostname, cdr_tds_config::hrtime, LOG_ERROR, LOG_NOTICE, mssql_connect(), mssql_disconnect(), settings, cdr_tds_config::table, and tds_lock.
Referenced by load_module().
00112 { 00113 char start[80], answer[80], end[80]; 00114 char *accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid, *userfield = NULL; 00115 RETCODE erc; 00116 int res = -1; 00117 int attempt = 1; 00118 00119 accountcode = anti_injection(cdr->accountcode, 20); 00120 src = anti_injection(cdr->src, 80); 00121 dst = anti_injection(cdr->dst, 80); 00122 dcontext = anti_injection(cdr->dcontext, 80); 00123 clid = anti_injection(cdr->clid, 80); 00124 channel = anti_injection(cdr->channel, 80); 00125 dstchannel = anti_injection(cdr->dstchannel, 80); 00126 lastapp = anti_injection(cdr->lastapp, 80); 00127 lastdata = anti_injection(cdr->lastdata, 80); 00128 uniqueid = anti_injection(cdr->uniqueid, 32); 00129 00130 get_date(start, sizeof(start), cdr->start); 00131 get_date(answer, sizeof(answer), cdr->answer); 00132 get_date(end, sizeof(end), cdr->end); 00133 00134 ast_mutex_lock(&tds_lock); 00135 00136 if (settings->has_userfield) { 00137 userfield = anti_injection(cdr->userfield, AST_MAX_USER_FIELD); 00138 } 00139 00140 retry: 00141 /* Ensure that we are connected */ 00142 if (!settings->connected) { 00143 ast_log(LOG_NOTICE, "Attempting to reconnect to %s (Attempt %d)\n", settings->hostname, attempt); 00144 if (mssql_connect()) { 00145 /* Connect failed */ 00146 if (attempt++ < 3) { 00147 goto retry; 00148 } 00149 goto done; 00150 } 00151 } 00152 00153 if (settings->has_userfield) { 00154 if (settings->hrtime) { 00155 double hrbillsec = 0.0; 00156 double hrduration; 00157 00158 if (!ast_tvzero(cdr->answer)) { 00159 hrbillsec = (double)(ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0); 00160 } 00161 hrduration = (double)(ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0); 00162 00163 erc = dbfcmd(settings->dbproc, 00164 "INSERT INTO %s " 00165 "(" 00166 "accountcode, src, dst, dcontext, clid, channel, " 00167 "dstchannel, lastapp, lastdata, start, answer, [end], duration, " 00168 "billsec, disposition, amaflags, uniqueid, userfield" 00169 ") " 00170 "VALUES " 00171 "(" 00172 "'%s', '%s', '%s', '%s', '%s', '%s', " 00173 "'%s', '%s', '%s', %s, %s, %s, %lf, " 00174 "%lf, '%s', '%s', '%s', '%s'" 00175 ")", 00176 settings->table, 00177 accountcode, src, dst, dcontext, clid, channel, 00178 dstchannel, lastapp, lastdata, start, answer, end, hrduration, 00179 hrbillsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid, 00180 userfield 00181 ); 00182 } else { 00183 erc = dbfcmd(settings->dbproc, 00184 "INSERT INTO %s " 00185 "(" 00186 "accountcode, src, dst, dcontext, clid, channel, " 00187 "dstchannel, lastapp, lastdata, start, answer, [end], duration, " 00188 "billsec, disposition, amaflags, uniqueid, userfield" 00189 ") " 00190 "VALUES " 00191 "(" 00192 "'%s', '%s', '%s', '%s', '%s', '%s', " 00193 "'%s', '%s', '%s', %s, %s, %s, %ld, " 00194 "%ld, '%s', '%s', '%s', '%s'" 00195 ")", 00196 settings->table, 00197 accountcode, src, dst, dcontext, clid, channel, 00198 dstchannel, lastapp, lastdata, start, answer, end, cdr->duration, 00199 cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid, 00200 userfield 00201 ); 00202 } 00203 } else { 00204 if (settings->hrtime) { 00205 double hrbillsec = 0.0; 00206 double hrduration; 00207 00208 if (!ast_tvzero(cdr->answer)) { 00209 hrbillsec = (double)(ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0); 00210 } 00211 hrduration = (double)(ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0); 00212 00213 erc = dbfcmd(settings->dbproc, 00214 "INSERT INTO %s " 00215 "(" 00216 "accountcode, src, dst, dcontext, clid, channel, " 00217 "dstchannel, lastapp, lastdata, start, answer, [end], duration, " 00218 "billsec, disposition, amaflags, uniqueid" 00219 ") " 00220 "VALUES " 00221 "(" 00222 "'%s', '%s', '%s', '%s', '%s', '%s', " 00223 "'%s', '%s', '%s', %s, %s, %s, %lf, " 00224 "%lf, '%s', '%s', '%s'" 00225 ")", 00226 settings->table, 00227 accountcode, src, dst, dcontext, clid, channel, 00228 dstchannel, lastapp, lastdata, start, answer, end, hrduration, 00229 hrbillsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid 00230 ); 00231 } else { 00232 erc = dbfcmd(settings->dbproc, 00233 "INSERT INTO %s " 00234 "(" 00235 "accountcode, src, dst, dcontext, clid, channel, " 00236 "dstchannel, lastapp, lastdata, start, answer, [end], duration, " 00237 "billsec, disposition, amaflags, uniqueid" 00238 ") " 00239 "VALUES " 00240 "(" 00241 "'%s', '%s', '%s', '%s', '%s', '%s', " 00242 "'%s', '%s', '%s', %s, %s, %s, %ld, " 00243 "%ld, '%s', '%s', '%s'" 00244 ")", 00245 settings->table, 00246 accountcode, src, dst, dcontext, clid, channel, 00247 dstchannel, lastapp, lastdata, start, answer, end, cdr->duration, 00248 cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid 00249 ); 00250 } 00251 } 00252 00253 if (erc == FAIL) { 00254 if (attempt++ < 3) { 00255 ast_log(LOG_NOTICE, "Failed to build INSERT statement, retrying...\n"); 00256 mssql_disconnect(); 00257 goto retry; 00258 } else { 00259 ast_log(LOG_ERROR, "Failed to build INSERT statement, no CDR was logged.\n"); 00260 goto done; 00261 } 00262 } 00263 00264 if (dbsqlexec(settings->dbproc) == FAIL) { 00265 if (attempt++ < 3) { 00266 ast_log(LOG_NOTICE, "Failed to execute INSERT statement, retrying...\n"); 00267 mssql_disconnect(); 00268 goto retry; 00269 } else { 00270 ast_log(LOG_ERROR, "Failed to execute INSERT statement, no CDR was logged.\n"); 00271 goto done; 00272 } 00273 } 00274 00275 /* Consume any results we might get back (this is more of a sanity check than 00276 * anything else, since an INSERT shouldn't return results). */ 00277 while (dbresults(settings->dbproc) != NO_MORE_RESULTS) { 00278 while (dbnextrow(settings->dbproc) != NO_MORE_ROWS); 00279 } 00280 00281 res = 0; 00282 00283 done: 00284 ast_mutex_unlock(&tds_lock); 00285 00286 ast_free(accountcode); 00287 ast_free(src); 00288 ast_free(dst); 00289 ast_free(dcontext); 00290 ast_free(clid); 00291 ast_free(channel); 00292 ast_free(dstchannel); 00293 ast_free(lastapp); 00294 ast_free(lastdata); 00295 ast_free(uniqueid); 00296 00297 if (userfield) { 00298 ast_free(userfield); 00299 } 00300 00301 return res; 00302 }
static int tds_message_handler | ( | DBPROCESS * | dbproc, | |
DBINT | msgno, | |||
int | msgstate, | |||
int | severity, | |||
char * | msgtext, | |||
char * | srvname, | |||
char * | procname, | |||
int | line | |||
) | [static] |
Definition at line 473 of file cdr_tds.c.
References ast_debug, ast_log(), and LOG_NOTICE.
Referenced by load_module().
00474 { 00475 ast_debug(1, "Msg %d, Level %d, State %d, Line %d\n", msgno, severity, msgstate, line); 00476 ast_log(LOG_NOTICE, "%s\n", msgtext); 00477 00478 return 0; 00479 }
static int tds_unload_module | ( | void | ) | [static] |
Definition at line 444 of file cdr_tds.c.
References ast_cdr_unregister(), ast_free, ast_mutex_lock, ast_mutex_unlock, ast_string_field_free_memory, mssql_disconnect(), settings, and tds_lock.
Referenced by unload_module().
00445 { 00446 if (settings) { 00447 ast_mutex_lock(&tds_lock); 00448 mssql_disconnect(); 00449 ast_mutex_unlock(&tds_lock); 00450 00451 ast_string_field_free_memory(settings); 00452 ast_free(settings); 00453 } 00454 00455 ast_cdr_unregister(name); 00456 00457 dbexit(); 00458 00459 return 0; 00460 }
static int unload_module | ( | void | ) | [static] |
Definition at line 627 of file cdr_tds.c.
References tds_unload_module().
00628 { 00629 return tds_unload_module(); 00630 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "FreeTDS CDR Backend" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } [static] |
struct ast_module_info* ast_module_info = &__mod_info [static] |
struct cdr_tds_config* settings [static] |
Definition at line 100 of file cdr_tds.c.
Referenced by load_module(), mssql_connect(), mssql_disconnect(), tds_load_module(), tds_log(), and tds_unload_module().
ast_mutex_t tds_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 98 of file cdr_tds.c.
Referenced by tds_load_module(), tds_log(), and tds_unload_module().