Fri Aug 17 00:17:27 2018

Asterisk developer's documentation


cdr_tds.c File Reference

FreeTDS CDR logger. More...

#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 char * anti_injection (const char *, int)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,"FreeTDS CDR Backend",.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CDR_DRIVER,)
 AST_MUTEX_DEFINE_STATIC (tds_lock)
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 const char config [] = "cdr_tds.conf"
static const char name [] = "FreeTDS (MSSQL)"
static struct cdr_tds_configsettings

Detailed Description

FreeTDS CDR logger.

See also

Definition in file cdr_tds.c.


Define Documentation

#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]

Definition at line 77 of file cdr_tds.c.


Function Documentation

static char * anti_injection ( const char *  str,
int  len 
) [static]

Definition at line 304 of file cdr_tds.c.

References ast_calloc, ast_log(), and LOG_ERROR.

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 }

AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_LOAD_ORDER  ,
"FreeTDS CDR Backend"  ,
load = load_module,
unload = unload_module,
reload = reload,
load_pri = AST_MODPRI_CDR_DRIVER 
)
AST_MUTEX_DEFINE_STATIC ( tds_lock   ) 
static int execute_and_consume ( DBPROCESS *  dbproc,
const char *  fmt,
  ... 
) [static]

Definition at line 350 of file cdr_tds.c.

References ast_free, and ast_vasprintf.

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       ast_free(buffer);
00364       return 1;
00365    }
00366 
00367    ast_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 *  dateField,
size_t  len,
struct timeval  when 
) [static]

Definition at line 338 of file cdr_tds.c.

References ast_copy_string(), ast_localtime(), ast_strftime(), ast_tvzero(), and DATE_FORMAT.

Referenced by tds_log().

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, 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::connected, cdr_tds_config::dbproc, execute_and_consume(), cdr_tds_config::has_userfield, LOG_ERROR, and LOG_NOTICE.

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, and cdr_tds_config::dbproc.

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_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, hostname, language, LOG_ERROR, LOG_NOTICE, mssql_connect(), mssql_disconnect(), and table.

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, LOG_ERROR, LOG_NOTICE, mssql_connect(), and mssql_disconnect().

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, and mssql_disconnect().

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 }


Variable Documentation

const char config[] = "cdr_tds.conf" [static]

Definition at line 80 of file cdr_tds.c.

const char name[] = "FreeTDS (MSSQL)" [static]

Definition at line 79 of file cdr_tds.c.

struct cdr_tds_config* settings [static]

Definition at line 100 of file cdr_tds.c.


Generated on 17 Aug 2018 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1