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