cel_tds.c File Reference

FreeTDS CEL logger. More...

#include "asterisk.h"
#include <time.h>
#include <math.h>
#include "asterisk/config.h"
#include "asterisk/channel.h"
#include "asterisk/cel.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include <sqlfront.h>
#include <sybdb.h>

Include dependency graph for cel_tds.c:

Go to the source code of this file.

Data Structures

struct  cel_tds_config

Defines

#define DATE_FORMAT   "%Y/%m/%d %T"
#define TDS_BACKEND_NAME   "CEL TDS logging backend"

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 void tds_log (struct ast_event *event)
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 CEL 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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, }
static struct ast_module_infoast_module_info = &__mod_info
static char * config = "cel_tds.conf"
static struct cel_tds_configsettings
static ast_mutex_t tds_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }


Detailed Description

FreeTDS CEL logger.

See also

Definition in file cel_tds.c.


Define Documentation

#define DATE_FORMAT   "%Y/%m/%d %T"

 *
 * Table Structure for `cel`
 *

CREATE TABLE [dbo].[cel] (
	[accountcode] [varchar] (20) NULL ,
	[cidname] [varchar] (80) NULL ,
	[cidnum] [varchar] (80) NULL ,
	[cidani] [varchar] (80) NULL ,
	[cidrdnis] [varchar] (80) NULL ,
	[ciddnid] [varchar] (80) NULL ,
	[exten] [varchar] (80) NULL ,
	[context] [varchar] (80) NULL ,
	[channame] [varchar] (80) NULL ,
	[appname] [varchar] (80) NULL ,
	[appdata] [varchar] (80) NULL ,
	[eventtime] [datetime] NULL ,
	[eventtype] [varchar] (32) NULL ,
	[uniqueid] [varchar] (32) NULL ,
	[linkedid] [varchar] (32) NULL ,
	[amaflags] [varchar] (16) NULL ,
	[userfield] [varchar] (32) NULL ,
	[peer] [varchar] (32) NULL
) ON [PRIMARY]

Definition at line 82 of file cel_tds.c.

#define TDS_BACKEND_NAME   "CEL TDS logging backend"

Definition at line 84 of file cel_tds.c.

Referenced by load_module(), and tds_unload_module().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 585 of file cel_tds.c.

static void __unreg_module ( void   )  [static]

Definition at line 585 of file cel_tds.c.

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

Definition at line 262 of file cel_tds.c.

References ast_calloc, ast_log, buf, LOG_ERROR, NULL, and strcasestr().

00263 {
00264    /* Reference to http://www.nextgenss.com/papers/advanced_sql_injection.pdf */
00265    char *buf;
00266    char *buf_ptr, *srh_ptr;
00267    char *known_bad[] = {"select", "insert", "update", "delete", "drop", ";", "--", "\0"};
00268    int idx;
00269 
00270    if (!(buf = ast_calloc(1, len + 1))) {
00271       ast_log(LOG_ERROR, "Out of memory\n");
00272       return NULL;
00273    }
00274 
00275    buf_ptr = buf;
00276 
00277    /* Escape single quotes */
00278    for (; *str && strlen(buf) < len; str++) {
00279       if (*str == '\'') {
00280          *buf_ptr++ = '\'';
00281       }
00282       *buf_ptr++ = *str;
00283    }
00284    *buf_ptr = '\0';
00285 
00286    /* Erase known bad input */
00287    for (idx = 0; *known_bad[idx]; idx++) {
00288       while ((srh_ptr = strcasestr(buf, known_bad[idx]))) {
00289          memmove(srh_ptr, srh_ptr + strlen(known_bad[idx]), strlen(srh_ptr + strlen(known_bad[idx])) + 1);
00290       }
00291    }
00292    return buf;
00293 }

static int execute_and_consume ( DBPROCESS *  dbproc,
const char *  fmt,
  ... 
) [static]

Definition at line 307 of file cel_tds.c.

References ast_free, and ast_vasprintf.

00308 {
00309    va_list ap;
00310    char *buffer;
00311 
00312    va_start(ap, fmt);
00313    if (ast_vasprintf(&buffer, fmt, ap) < 0) {
00314       va_end(ap);
00315       return 1;
00316    }
00317    va_end(ap);
00318 
00319    if (dbfcmd(dbproc, buffer) == FAIL) {
00320       ast_free(buffer);
00321       return 1;
00322    }
00323 
00324    ast_free(buffer);
00325 
00326    if (dbsqlexec(dbproc) == FAIL) {
00327       return 1;
00328    }
00329 
00330    /* Consume the result set (we don't really care about the result, though) */
00331    while (dbresults(dbproc) != NO_MORE_RESULTS) {
00332       while (dbnextrow(dbproc) != NO_MORE_ROWS);
00333    }
00334 
00335    return 0;
00336 }

static void get_date ( char *  dateField,
size_t  len,
struct timeval  when 
) [static]

Definition at line 295 of file cel_tds.c.

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

00296 {
00297    /* To make sure we have date variable if not insert null to SQL */
00298    if (!ast_tvzero(when)) {
00299       struct ast_tm tm;
00300       ast_localtime(&when, &tm, NULL);
00301       ast_strftime(dateField, len, "'" DATE_FORMAT "'", &tm);
00302    } else {
00303       ast_copy_string(dateField, "null", len);
00304    }
00305 }

static int load_module ( void   )  [static]

Definition at line 535 of file cel_tds.c.

References ast_calloc_with_stringfields, ast_cel_backend_register(), ast_free, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_string_field_free_memory, LOG_ERROR, LOG_WARNING, NULL, TDS_BACKEND_NAME, tds_error_handler(), tds_load_module(), tds_log(), and tds_message_handler().

00536 {
00537    if (dbinit() == FAIL) {
00538       ast_log(LOG_ERROR, "Failed to initialize FreeTDS db-lib\n");
00539       return AST_MODULE_LOAD_DECLINE;
00540    }
00541 
00542    dberrhandle(tds_error_handler);
00543    dbmsghandle(tds_message_handler);
00544 
00545    settings = ast_calloc_with_stringfields(1, struct cel_tds_config, 256);
00546 
00547    if (!settings) {
00548       dbexit();
00549       return AST_MODULE_LOAD_DECLINE;
00550    }
00551 
00552    if (!tds_load_module(0)) {
00553       ast_string_field_free_memory(settings);
00554       ast_free(settings);
00555       settings = NULL;
00556       dbexit();
00557       ast_log(LOG_WARNING,"cel_tds module had config problems; declining load\n");
00558       return AST_MODULE_LOAD_DECLINE;
00559    }
00560 
00561    /* Register MSSQL CEL handler */
00562    if (ast_cel_backend_register(TDS_BACKEND_NAME, tds_log)) {
00563       ast_log(LOG_ERROR, "Unable to register MSSQL CEL handling\n");
00564       ast_string_field_free_memory(settings);
00565       ast_free(settings);
00566       settings = NULL;
00567       dbexit();
00568       return AST_MODULE_LOAD_DECLINE;
00569    }
00570 
00571    return AST_MODULE_LOAD_SUCCESS;
00572 }

static int mssql_connect ( void   )  [static]

Definition at line 349 of file cel_tds.c.

References ast_log, ast_strlen_zero, cel_tds_config::charset, cel_tds_config::connected, cel_tds_config::connection, cel_tds_config::database, dbopen(), cel_tds_config::dbproc, execute_and_consume(), cel_tds_config::language, LOG_ERROR, NULL, cel_tds_config::password, cel_tds_config::table, and cel_tds_config::username.

00350 {
00351    LOGINREC *login;
00352 
00353    if ((login = dblogin()) == NULL) {
00354       ast_log(LOG_ERROR, "Unable to allocate login structure for db-lib\n");
00355       return -1;
00356    }
00357 
00358    DBSETLAPP(login,  "TSQL");
00359    DBSETLUSER(login, (char *) settings->username);
00360    DBSETLPWD(login,  (char *) settings->password);
00361 
00362    if (!ast_strlen_zero(settings->charset)) {
00363       DBSETLCHARSET(login, (char *) settings->charset);
00364    }
00365 
00366    if (!ast_strlen_zero(settings->language)) {
00367       DBSETLNATLANG(login, (char *) settings->language);
00368    }
00369 
00370    if ((settings->dbproc = dbopen(login, (char *) settings->connection)) == NULL) {
00371       ast_log(LOG_ERROR, "Unable to connect to %s\n", settings->connection);
00372       dbloginfree(login);
00373       return -1;
00374    }
00375 
00376    dbloginfree(login);
00377 
00378    if (dbuse(settings->dbproc, (char *) settings->database) == FAIL) {
00379       ast_log(LOG_ERROR, "Unable to select database %s\n", settings->database);
00380       goto failed;
00381    }
00382 
00383    if (execute_and_consume(settings->dbproc, "SELECT 1 FROM [%s]", settings->table)) {
00384       ast_log(LOG_ERROR, "Unable to find table '%s'\n", settings->table);
00385       goto failed;
00386    }
00387 
00388    settings->connected = 1;
00389 
00390    return 0;
00391 
00392 failed:
00393    dbclose(settings->dbproc);
00394    settings->dbproc = NULL;
00395    return -1;
00396 }

static int mssql_disconnect ( void   )  [static]

Definition at line 338 of file cel_tds.c.

References cel_tds_config::connected, cel_tds_config::dbproc, and NULL.

00339 {
00340    if (settings->dbproc) {
00341       dbclose(settings->dbproc);
00342       settings->dbproc = NULL;
00343    }
00344    settings->connected = 0;
00345 
00346    return 0;
00347 }

static int reload ( void   )  [static]

Definition at line 530 of file cel_tds.c.

References tds_load_module().

00531 {
00532    return tds_load_module(1);
00533 }

static int tds_error_handler ( DBPROCESS *  dbproc,
int  severity,
int  dberr,
int  oserr,
char *  dberrstr,
char *  oserrstr 
) [static]

Definition at line 416 of file cel_tds.c.

References ast_log, and LOG_ERROR.

00417 {
00418    ast_log(LOG_ERROR, "%s (%d)\n", dberrstr, dberr);
00419 
00420    if (oserr != DBNOERR) {
00421       ast_log(LOG_ERROR, "%s (%d)\n", oserrstr, oserr);
00422    }
00423 
00424    return INT_CANCEL;
00425 }

static int tds_load_module ( int  reload  )  [static]

Definition at line 435 of file cel_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_variable_browse(), ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, language, LOG_ERROR, LOG_NOTICE, mssql_connect(), mssql_disconnect(), NULL, password, table, and tds_lock.

00436 {
00437    struct ast_config *cfg;
00438    const char *ptr = NULL;
00439    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00440 
00441    cfg = ast_config_load(config, config_flags);
00442    if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
00443       ast_log(LOG_NOTICE, "Unable to load TDS config for CELs: %s\n", config);
00444       return 0;
00445    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
00446       return 0;
00447    }
00448 
00449    if (!ast_variable_browse(cfg, "global")) {
00450       /* nothing configured */
00451       ast_config_destroy(cfg);
00452       ast_log(LOG_NOTICE, "cel_tds has no global category, nothing to configure.\n");
00453       return 0;
00454    }
00455 
00456    ast_mutex_lock(&tds_lock);
00457 
00458    /* Clear out any existing settings */
00459    ast_string_field_init(settings, 0);
00460 
00461    ptr = ast_variable_retrieve(cfg, "global", "connection");
00462    if (ptr) {
00463       ast_string_field_set(settings, connection, ptr);
00464    } else {
00465       ast_log(LOG_ERROR, "Failed to connect: Database connection name not specified.\n");
00466       goto failed;
00467    }
00468 
00469    ptr = ast_variable_retrieve(cfg, "global", "dbname");
00470    if (ptr) {
00471       ast_string_field_set(settings, database, ptr);
00472    } else {
00473       ast_log(LOG_ERROR, "Failed to connect: Database dbname not specified.\n");
00474       goto failed;
00475    }
00476 
00477    ptr = ast_variable_retrieve(cfg, "global", "user");
00478    if (ptr) {
00479       ast_string_field_set(settings, username, ptr);
00480    } else {
00481       ast_log(LOG_ERROR, "Failed to connect: Database dbuser not specified.\n");
00482       goto failed;
00483    }
00484 
00485    ptr = ast_variable_retrieve(cfg, "global", "password");
00486    if (ptr) {
00487       ast_string_field_set(settings, password, ptr);
00488    } else {
00489       ast_log(LOG_ERROR, "Failed to connect: Database password not specified.\n");
00490       goto failed;
00491    }
00492 
00493    ptr = ast_variable_retrieve(cfg, "global", "charset");
00494    if (ptr) {
00495       ast_string_field_set(settings, charset, ptr);
00496    }
00497 
00498    ptr = ast_variable_retrieve(cfg, "global", "language");
00499    if (ptr) {
00500       ast_string_field_set(settings, language, ptr);
00501    }
00502 
00503    ptr = ast_variable_retrieve(cfg, "global", "table");
00504    if (ptr) {
00505       ast_string_field_set(settings, table, ptr);
00506    } else {
00507       ast_log(LOG_NOTICE, "Table name not specified, using 'cel' by default.\n");
00508       ast_string_field_set(settings, table, "cel");
00509    }
00510 
00511    mssql_disconnect();
00512 
00513    if (mssql_connect()) {
00514       /* We failed to connect (mssql_connect takes care of logging it) */
00515       goto failed;
00516    }
00517 
00518    ast_mutex_unlock(&tds_lock);
00519    ast_config_destroy(cfg);
00520 
00521    return 1;
00522 
00523 failed:
00524    ast_mutex_unlock(&tds_lock);
00525    ast_config_destroy(cfg);
00526 
00527    return 0;
00528 }

static void tds_log ( struct ast_event event  )  [static]

Definition at line 115 of file cel_tds.c.

References ast_cel_event_record::account_code, ast_cel_event_record::amaflag, anti_injection(), ast_cel_event_record::application_data, ast_cel_event_record::application_name, AST_CEL_EVENT_RECORD_VERSION, ast_cel_fill_record(), AST_CEL_USER_DEFINED, ast_channel_amaflags2string(), ast_free, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_cel_event_record::caller_id_ani, ast_cel_event_record::caller_id_dnid, ast_cel_event_record::caller_id_name, ast_cel_event_record::caller_id_num, ast_cel_event_record::caller_id_rdnis, ast_cel_event_record::channel_name, cel_tds_config::connected, cel_tds_config::connection, ast_cel_event_record::context, cel_tds_config::dbproc, ast_cel_event_record::event_name, ast_cel_event_record::event_time, ast_cel_event_record::event_type, ast_cel_event_record::extension, get_date(), ast_cel_event_record::linked_id, LOG_ERROR, LOG_NOTICE, mssql_connect(), mssql_disconnect(), ast_cel_event_record::peer, cel_tds_config::table, tds_lock, ast_cel_event_record::unique_id, ast_cel_event_record::user_defined_name, ast_cel_event_record::user_field, and ast_cel_event_record::version.

00116 {
00117    char start[80];
00118    char *accountcode_ai, *clidnum_ai, *exten_ai, *context_ai, *clid_ai, *channel_ai, *app_ai, *appdata_ai, *uniqueid_ai, *linkedid_ai, *cidani_ai, *cidrdnis_ai, *ciddnid_ai, *peer_ai, *userfield_ai;
00119    RETCODE erc;
00120    int attempt = 1;
00121    struct ast_cel_event_record record = {
00122       .version = AST_CEL_EVENT_RECORD_VERSION,
00123    };
00124 
00125    if (ast_cel_fill_record(event, &record)) {
00126       return;
00127    }
00128 
00129    ast_mutex_lock(&tds_lock);
00130 
00131    accountcode_ai = anti_injection(record.account_code, 20);
00132    clidnum_ai     = anti_injection(record.caller_id_num, 80);
00133    clid_ai        = anti_injection(record.caller_id_name, 80);
00134    cidani_ai      = anti_injection(record.caller_id_ani, 80);
00135    cidrdnis_ai    = anti_injection(record.caller_id_rdnis, 80);
00136    ciddnid_ai     = anti_injection(record.caller_id_dnid, 80);
00137    exten_ai       = anti_injection(record.extension, 80);
00138    context_ai     = anti_injection(record.context, 80);
00139    channel_ai     = anti_injection(record.channel_name, 80);
00140    app_ai         = anti_injection(record.application_name, 80);
00141    appdata_ai     = anti_injection(record.application_data, 80);
00142    uniqueid_ai    = anti_injection(record.unique_id, 32);
00143    linkedid_ai    = anti_injection(record.linked_id, 32);
00144    userfield_ai   = anti_injection(record.user_field, 32);
00145    peer_ai        = anti_injection(record.peer, 32);
00146 
00147    get_date(start, sizeof(start), record.event_time);
00148 
00149 retry:
00150    /* Ensure that we are connected */
00151    if (!settings->connected) {
00152       ast_log(LOG_NOTICE, "Attempting to reconnect to %s (Attempt %d)\n", settings->connection, attempt);
00153       if (mssql_connect()) {
00154          /* Connect failed */
00155          if (attempt++ < 3) {
00156             goto retry;
00157          }
00158          goto done;
00159       }
00160    }
00161 
00162    erc = dbfcmd(settings->dbproc,
00163       "INSERT INTO %s "
00164       "("
00165       "accountcode,"
00166       "cidnum,"
00167       "cidname,"
00168       "cidani,"
00169       "cidrdnis,"
00170       "ciddnid,"
00171       "exten,"
00172       "context,"
00173       "channel,"
00174       "appname,"
00175       "appdata,"
00176       "eventtime,"
00177       "eventtype,"
00178       "amaflags, "
00179       "uniqueid,"
00180       "linkedid,"
00181       "userfield,"
00182       "peer"
00183       ") "
00184       "VALUES "
00185       "("
00186       "'%s',"  /* accountcode */
00187       "'%s',"  /* clidnum */
00188       "'%s',"  /* clid */
00189       "'%s',"  /* cid-ani */
00190       "'%s',"  /* cid-rdnis */
00191       "'%s',"  /* cid-dnid */
00192       "'%s',"  /* exten */
00193       "'%s',"  /* context */
00194       "'%s',"  /* channel */
00195       "'%s',"  /* app */
00196       "'%s',"  /* appdata */
00197       "%s, "   /* eventtime */
00198       "'%s',"  /* eventtype */
00199       "'%s',"  /* amaflags */
00200       "'%s',"  /* uniqueid */
00201       "'%s',"  /* linkedid */
00202       "'%s',"  /* userfield */
00203       "'%s'"   /* peer */
00204       ")",
00205       settings->table, accountcode_ai, clidnum_ai, clid_ai, cidani_ai, cidrdnis_ai,
00206       ciddnid_ai, exten_ai, context_ai, channel_ai, app_ai, appdata_ai, start,
00207       (record.event_type == AST_CEL_USER_DEFINED)
00208          ? record.user_defined_name : record.event_name,
00209                ast_channel_amaflags2string(record.amaflag), uniqueid_ai, linkedid_ai,
00210       userfield_ai, peer_ai);
00211 
00212    if (erc == FAIL) {
00213       if (attempt++ < 3) {
00214          ast_log(LOG_NOTICE, "Failed to build INSERT statement, retrying...\n");
00215          mssql_disconnect();
00216          goto retry;
00217       } else {
00218          ast_log(LOG_ERROR, "Failed to build INSERT statement, no CEL was logged.\n");
00219          goto done;
00220       }
00221    }
00222 
00223    if (dbsqlexec(settings->dbproc) == FAIL) {
00224       if (attempt++ < 3) {
00225          ast_log(LOG_NOTICE, "Failed to execute INSERT statement, retrying...\n");
00226          mssql_disconnect();
00227          goto retry;
00228       } else {
00229          ast_log(LOG_ERROR, "Failed to execute INSERT statement, no CEL was logged.\n");
00230          goto done;
00231       }
00232    }
00233 
00234    /* Consume any results we might get back (this is more of a sanity check than
00235     * anything else, since an INSERT shouldn't return results). */
00236    while (dbresults(settings->dbproc) != NO_MORE_RESULTS) {
00237       while (dbnextrow(settings->dbproc) != NO_MORE_ROWS);
00238    }
00239 
00240 done:
00241    ast_mutex_unlock(&tds_lock);
00242 
00243    ast_free(accountcode_ai);
00244    ast_free(clidnum_ai);
00245    ast_free(clid_ai);
00246    ast_free(cidani_ai);
00247    ast_free(cidrdnis_ai);
00248    ast_free(ciddnid_ai);
00249    ast_free(exten_ai);
00250    ast_free(context_ai);
00251    ast_free(channel_ai);
00252    ast_free(app_ai);
00253    ast_free(appdata_ai);
00254    ast_free(uniqueid_ai);
00255    ast_free(linkedid_ai);
00256    ast_free(userfield_ai);
00257    ast_free(peer_ai);
00258 
00259    return;
00260 }

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 427 of file cel_tds.c.

References ast_debug, ast_log, and LOG_NOTICE.

00428 {
00429    ast_debug(1, "Msg %d, Level %d, State %d, Line %d\n", msgno, severity, msgstate, line);
00430    ast_log(LOG_NOTICE, "%s\n", msgtext);
00431 
00432    return 0;
00433 }

static int tds_unload_module ( void   )  [static]

Definition at line 398 of file cel_tds.c.

References ast_cel_backend_unregister(), ast_free, ast_mutex_lock, ast_mutex_unlock, ast_string_field_free_memory, mssql_disconnect(), TDS_BACKEND_NAME, and tds_lock.

00399 {
00400    ast_cel_backend_unregister(TDS_BACKEND_NAME);
00401 
00402    if (settings) {
00403       ast_mutex_lock(&tds_lock);
00404       mssql_disconnect();
00405       ast_mutex_unlock(&tds_lock);
00406 
00407       ast_string_field_free_memory(settings);
00408       ast_free(settings);
00409    }
00410 
00411    dbexit();
00412 
00413    return 0;
00414 }

static int unload_module ( void   )  [static]

Definition at line 574 of file cel_tds.c.

References tds_unload_module().

00575 {
00576    return tds_unload_module();
00577 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "FreeTDS CEL 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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } [static]

Definition at line 585 of file cel_tds.c.

Definition at line 585 of file cel_tds.c.

char* config = "cel_tds.conf" [static]

Definition at line 86 of file cel_tds.c.

struct cel_tds_config* settings [static]

Definition at line 104 of file cel_tds.c.

ast_mutex_t tds_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

Definition at line 102 of file cel_tds.c.


Generated on Thu Apr 16 06:29:30 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6