Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
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
 

Macros

#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)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, .requires = "cel", }
 
static const 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_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 

Detailed Description

FreeTDS CEL logger.

See also

Definition in file cel_tds.c.

Macro Definition Documentation

◆ DATE_FORMAT

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

Referenced by get_date().

◆ TDS_BACKEND_NAME

#define TDS_BACKEND_NAME   "CEL TDS logging backend"

Definition at line 82 of file cel_tds.c.

Referenced by load_module(), and tds_unload_module().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 584 of file cel_tds.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 584 of file cel_tds.c.

◆ anti_injection()

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

Definition at line 260 of file cel_tds.c.

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

Referenced by tds_log().

261 {
262  /* Reference to http://www.nextgenss.com/papers/advanced_sql_injection.pdf */
263  char *buf;
264  char *buf_ptr, *srh_ptr;
265  char *known_bad[] = {"select", "insert", "update", "delete", "drop", ";", "--", "\0"};
266  int idx;
267 
268  if (!(buf = ast_calloc(1, len + 1))) {
269  ast_log(LOG_ERROR, "Out of memory\n");
270  return NULL;
271  }
272 
273  buf_ptr = buf;
274 
275  /* Escape single quotes */
276  for (; *str && strlen(buf) < len; str++) {
277  if (*str == '\'') {
278  *buf_ptr++ = '\'';
279  }
280  *buf_ptr++ = *str;
281  }
282  *buf_ptr = '\0';
283 
284  /* Erase known bad input */
285  for (idx = 0; *known_bad[idx]; idx++) {
286  while ((srh_ptr = strcasestr(buf, known_bad[idx]))) {
287  memmove(srh_ptr, srh_ptr + strlen(known_bad[idx]), strlen(srh_ptr + strlen(known_bad[idx])) + 1);
288  }
289  }
290  return buf;
291 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * strcasestr(const char *, const char *)
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 584 of file cel_tds.c.

◆ execute_and_consume()

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

Definition at line 305 of file cel_tds.c.

References ast_free, and ast_vasprintf.

Referenced by mssql_connect().

306 {
307  va_list ap;
308  char *buffer;
309 
310  va_start(ap, fmt);
311  if (ast_vasprintf(&buffer, fmt, ap) < 0) {
312  va_end(ap);
313  return 1;
314  }
315  va_end(ap);
316 
317  if (dbfcmd(dbproc, buffer) == FAIL) {
318  ast_free(buffer);
319  return 1;
320  }
321 
322  ast_free(buffer);
323 
324  if (dbsqlexec(dbproc) == FAIL) {
325  return 1;
326  }
327 
328  /* Consume the result set (we don't really care about the result, though) */
329  while (dbresults(dbproc) != NO_MORE_RESULTS) {
330  while (dbnextrow(dbproc) != NO_MORE_ROWS);
331  }
332 
333  return 0;
334 }
#define ast_vasprintf(ret, fmt, ap)
A wrapper for vasprintf()
Definition: astmm.h:280
#define ast_free(a)
Definition: astmm.h:182

◆ get_date()

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

Definition at line 293 of file cel_tds.c.

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

Referenced by tds_log().

294 {
295  /* To make sure we have date variable if not insert null to SQL */
296  if (!ast_tvzero(when)) {
297  struct ast_tm tm;
298  ast_localtime(&when, &tm, NULL);
299  ast_strftime(dateField, len, "'" DATE_FORMAT "'", &tm);
300  } else {
301  ast_copy_string(dateField, "null", len);
302  }
303 }
#define DATE_FORMAT
Definition: cel_tds.c:80
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
#define NULL
Definition: resample.c:96
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ load_module()

static int load_module ( void  )
static

Definition at line 533 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().

Referenced by unload_module().

534 {
535  if (dbinit() == FAIL) {
536  ast_log(LOG_ERROR, "Failed to initialize FreeTDS db-lib\n");
538  }
539 
540  dberrhandle(tds_error_handler);
541  dbmsghandle(tds_message_handler);
542 
544 
545  if (!settings) {
546  dbexit();
548  }
549 
550  if (!tds_load_module(0)) {
553  settings = NULL;
554  dbexit();
555  ast_log(LOG_WARNING,"cel_tds module had config problems; declining load\n");
557  }
558 
559  /* Register MSSQL CEL handler */
561  ast_log(LOG_ERROR, "Unable to register MSSQL CEL handling\n");
564  settings = NULL;
565  dbexit();
567  }
568 
570 }
int ast_cel_backend_register(const char *name, ast_cel_backend_cb backend_callback)
Register a CEL backend.
Definition: cel.c:1740
#define LOG_WARNING
Definition: logger.h:274
#define TDS_BACKEND_NAME
Definition: cel_tds.c:82
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:426
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
static struct cel_tds_config * settings
Definition: cel_tds.c:102
static int tds_error_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
Definition: cel_tds.c:414
#define LOG_ERROR
Definition: logger.h:285
#define ast_free(a)
Definition: astmm.h:182
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static int tds_load_module(int reload)
Definition: cel_tds.c:433
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
static int tds_message_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line)
Definition: cel_tds.c:425
static void tds_log(struct ast_event *event)
Definition: cel_tds.c:113

◆ mssql_connect()

static int mssql_connect ( void  )
static

Definition at line 347 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.

Referenced by tds_load_module(), and tds_log().

348 {
349  LOGINREC *login;
350 
351  if ((login = dblogin()) == NULL) {
352  ast_log(LOG_ERROR, "Unable to allocate login structure for db-lib\n");
353  return -1;
354  }
355 
356  DBSETLAPP(login, "TSQL");
357  DBSETLUSER(login, (char *) settings->username);
358  DBSETLPWD(login, (char *) settings->password);
359 
361  DBSETLCHARSET(login, (char *) settings->charset);
362  }
363 
365  DBSETLNATLANG(login, (char *) settings->language);
366  }
367 
368  if ((settings->dbproc = dbopen(login, (char *) settings->connection)) == NULL) {
369  ast_log(LOG_ERROR, "Unable to connect to %s\n", settings->connection);
370  dbloginfree(login);
371  return -1;
372  }
373 
374  dbloginfree(login);
375 
376  if (dbuse(settings->dbproc, (char *) settings->database) == FAIL) {
377  ast_log(LOG_ERROR, "Unable to select database %s\n", settings->database);
378  goto failed;
379  }
380 
381  if (execute_and_consume(settings->dbproc, "SELECT 1 FROM [%s]", settings->table)) {
382  ast_log(LOG_ERROR, "Unable to find table '%s'\n", settings->table);
383  goto failed;
384  }
385 
386  settings->connected = 1;
387 
388  return 0;
389 
390 failed:
391  dbclose(settings->dbproc);
392  settings->dbproc = NULL;
393  return -1;
394 }
const ast_string_field charset
Definition: cel_tds.c:95
#define NULL
Definition: resample.c:96
const ast_string_field username
Definition: cel_tds.c:95
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
static int execute_and_consume(DBPROCESS *dbproc, const char *fmt,...)
Definition: cel_tds.c:305
static struct cel_tds_config * settings
Definition: cel_tds.c:102
const ast_string_field connection
Definition: cel_tds.c:95
DBPROCESS * dbproc
Definition: cel_tds.c:96
#define LOG_ERROR
Definition: logger.h:285
const ast_string_field database
Definition: cel_tds.c:95
const ast_string_field table
Definition: cel_tds.c:95
const ast_string_field password
Definition: cel_tds.c:95
const ast_string_field language
Definition: cel_tds.c:95
unsigned int connected
Definition: cel_tds.c:97
DB * dbopen(char *fname, int flags, int mode, DBTYPE type, const void *openinfo) const

◆ mssql_disconnect()

static int mssql_disconnect ( void  )
static

Definition at line 336 of file cel_tds.c.

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

Referenced by tds_load_module(), tds_log(), and tds_unload_module().

337 {
338  if (settings->dbproc) {
339  dbclose(settings->dbproc);
340  settings->dbproc = NULL;
341  }
342  settings->connected = 0;
343 
344  return 0;
345 }
#define NULL
Definition: resample.c:96
static struct cel_tds_config * settings
Definition: cel_tds.c:102
DBPROCESS * dbproc
Definition: cel_tds.c:96
unsigned int connected
Definition: cel_tds.c:97

◆ reload()

static int reload ( void  )
static

Definition at line 528 of file cel_tds.c.

References tds_load_module().

Referenced by unload_module().

529 {
530  return tds_load_module(1);
531 }
static int tds_load_module(int reload)
Definition: cel_tds.c:433

◆ tds_error_handler()

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

Definition at line 414 of file cel_tds.c.

References ast_log, and LOG_ERROR.

Referenced by load_module().

415 {
416  ast_log(LOG_ERROR, "%s (%d)\n", dberrstr, dberr);
417 
418  if (oserr != DBNOERR) {
419  ast_log(LOG_ERROR, "%s (%d)\n", oserrstr, oserr);
420  }
421 
422  return INT_CANCEL;
423 }
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285

◆ tds_load_module()

static int tds_load_module ( int  reload)
static

Definition at line 433 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, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, cel_tds_config::connection, cel_tds_config::database, cel_tds_config::language, LOG_ERROR, LOG_NOTICE, mssql_connect(), mssql_disconnect(), NULL, cel_tds_config::password, cel_tds_config::table, tds_lock, and cel_tds_config::username.

Referenced by load_module(), and reload().

434 {
435  struct ast_config *cfg;
436  const char *ptr = NULL;
437  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
438 
439  cfg = ast_config_load(config, config_flags);
440  if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
441  ast_log(LOG_NOTICE, "Unable to load TDS config for CELs: %s\n", config);
442  return 0;
443  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
444  return 0;
445  }
446 
447  if (!ast_variable_browse(cfg, "global")) {
448  /* nothing configured */
449  ast_config_destroy(cfg);
450  ast_log(LOG_NOTICE, "cel_tds has no global category, nothing to configure.\n");
451  return 0;
452  }
453 
455 
456  /* Clear out any existing settings */
458 
459  ptr = ast_variable_retrieve(cfg, "global", "connection");
460  if (ptr) {
461  ast_string_field_set(settings, connection, ptr);
462  } else {
463  ast_log(LOG_ERROR, "Failed to connect: Database connection name not specified.\n");
464  goto failed;
465  }
466 
467  ptr = ast_variable_retrieve(cfg, "global", "dbname");
468  if (ptr) {
469  ast_string_field_set(settings, database, ptr);
470  } else {
471  ast_log(LOG_ERROR, "Failed to connect: Database dbname not specified.\n");
472  goto failed;
473  }
474 
475  ptr = ast_variable_retrieve(cfg, "global", "user");
476  if (ptr) {
477  ast_string_field_set(settings, username, ptr);
478  } else {
479  ast_log(LOG_ERROR, "Failed to connect: Database dbuser not specified.\n");
480  goto failed;
481  }
482 
483  ptr = ast_variable_retrieve(cfg, "global", "password");
484  if (ptr) {
486  } else {
487  ast_log(LOG_ERROR, "Failed to connect: Database password not specified.\n");
488  goto failed;
489  }
490 
491  ptr = ast_variable_retrieve(cfg, "global", "charset");
492  if (ptr) {
494  }
495 
496  ptr = ast_variable_retrieve(cfg, "global", "language");
497  if (ptr) {
499  }
500 
501  ptr = ast_variable_retrieve(cfg, "global", "table");
502  if (ptr) {
504  } else {
505  ast_log(LOG_NOTICE, "Table name not specified, using 'cel' by default.\n");
507  }
508 
510 
511  if (mssql_connect()) {
512  /* We failed to connect (mssql_connect takes care of logging it) */
513  goto failed;
514  }
515 
517  ast_config_destroy(cfg);
518 
519  return 1;
520 
521 failed:
523  ast_config_destroy(cfg);
524 
525  return 0;
526 }
static ast_mutex_t tds_lock
Definition: cel_tds.c:100
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define CONFIG_STATUS_FILEINVALID
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
static int mssql_disconnect(void)
Definition: cel_tds.c:336
static struct ast_str * password
Definition: cdr_mysql.c:77
static char * table
Definition: cdr_odbc.c:58
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
static struct cel_tds_config * settings
Definition: cel_tds.c:102
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:117
#define CONFIG_STATUS_FILEUNCHANGED
#define LOG_ERROR
Definition: logger.h:285
#define LOG_NOTICE
Definition: logger.h:263
charset
Definition: chan_unistim.c:336
Structure used to handle boolean flags.
Definition: utils.h:199
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
static int reload(void)
Definition: cel_tds.c:528
static int mssql_connect(void)
Definition: cel_tds.c:347
static char * config
Definition: cel_tds.c:84
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ tds_log()

static void tds_log ( struct ast_event event)
static

Definition at line 113 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, done, 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.

Referenced by load_module().

114 {
115  char start[80];
116  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;
117  RETCODE erc;
118  int attempt = 1;
119  struct ast_cel_event_record record = {
121  };
122 
123  if (ast_cel_fill_record(event, &record)) {
124  return;
125  }
126 
128 
129  accountcode_ai = anti_injection(record.account_code, 20);
130  clidnum_ai = anti_injection(record.caller_id_num, 80);
131  clid_ai = anti_injection(record.caller_id_name, 80);
132  cidani_ai = anti_injection(record.caller_id_ani, 80);
133  cidrdnis_ai = anti_injection(record.caller_id_rdnis, 80);
134  ciddnid_ai = anti_injection(record.caller_id_dnid, 80);
135  exten_ai = anti_injection(record.extension, 80);
136  context_ai = anti_injection(record.context, 80);
137  channel_ai = anti_injection(record.channel_name, 80);
138  app_ai = anti_injection(record.application_name, 80);
139  appdata_ai = anti_injection(record.application_data, 80);
140  uniqueid_ai = anti_injection(record.unique_id, 32);
141  linkedid_ai = anti_injection(record.linked_id, 32);
142  userfield_ai = anti_injection(record.user_field, 32);
143  peer_ai = anti_injection(record.peer, 32);
144 
145  get_date(start, sizeof(start), record.event_time);
146 
147 retry:
148  /* Ensure that we are connected */
149  if (!settings->connected) {
150  ast_log(LOG_NOTICE, "Attempting to reconnect to %s (Attempt %d)\n", settings->connection, attempt);
151  if (mssql_connect()) {
152  /* Connect failed */
153  if (attempt++ < 3) {
154  goto retry;
155  }
156  goto done;
157  }
158  }
159 
160  erc = dbfcmd(settings->dbproc,
161  "INSERT INTO %s "
162  "("
163  "accountcode,"
164  "cidnum,"
165  "cidname,"
166  "cidani,"
167  "cidrdnis,"
168  "ciddnid,"
169  "exten,"
170  "context,"
171  "channel,"
172  "appname,"
173  "appdata,"
174  "eventtime,"
175  "eventtype,"
176  "amaflags, "
177  "uniqueid,"
178  "linkedid,"
179  "userfield,"
180  "peer"
181  ") "
182  "VALUES "
183  "("
184  "'%s'," /* accountcode */
185  "'%s'," /* clidnum */
186  "'%s'," /* clid */
187  "'%s'," /* cid-ani */
188  "'%s'," /* cid-rdnis */
189  "'%s'," /* cid-dnid */
190  "'%s'," /* exten */
191  "'%s'," /* context */
192  "'%s'," /* channel */
193  "'%s'," /* app */
194  "'%s'," /* appdata */
195  "%s, " /* eventtime */
196  "'%s'," /* eventtype */
197  "'%s'," /* amaflags */
198  "'%s'," /* uniqueid */
199  "'%s'," /* linkedid */
200  "'%s'," /* userfield */
201  "'%s'" /* peer */
202  ")",
203  settings->table, accountcode_ai, clidnum_ai, clid_ai, cidani_ai, cidrdnis_ai,
204  ciddnid_ai, exten_ai, context_ai, channel_ai, app_ai, appdata_ai, start,
205  (record.event_type == AST_CEL_USER_DEFINED)
206  ? record.user_defined_name : record.event_name,
207  ast_channel_amaflags2string(record.amaflag), uniqueid_ai, linkedid_ai,
208  userfield_ai, peer_ai);
209 
210  if (erc == FAIL) {
211  if (attempt++ < 3) {
212  ast_log(LOG_NOTICE, "Failed to build INSERT statement, retrying...\n");
214  goto retry;
215  } else {
216  ast_log(LOG_ERROR, "Failed to build INSERT statement, no CEL was logged.\n");
217  goto done;
218  }
219  }
220 
221  if (dbsqlexec(settings->dbproc) == FAIL) {
222  if (attempt++ < 3) {
223  ast_log(LOG_NOTICE, "Failed to execute INSERT statement, retrying...\n");
225  goto retry;
226  } else {
227  ast_log(LOG_ERROR, "Failed to execute INSERT statement, no CEL was logged.\n");
228  goto done;
229  }
230  }
231 
232  /* Consume any results we might get back (this is more of a sanity check than
233  * anything else, since an INSERT shouldn't return results). */
234  while (dbresults(settings->dbproc) != NO_MORE_RESULTS) {
235  while (dbnextrow(settings->dbproc) != NO_MORE_ROWS);
236  }
237 
238 done:
240 
241  ast_free(accountcode_ai);
242  ast_free(clidnum_ai);
243  ast_free(clid_ai);
244  ast_free(cidani_ai);
245  ast_free(cidrdnis_ai);
246  ast_free(ciddnid_ai);
247  ast_free(exten_ai);
248  ast_free(context_ai);
249  ast_free(channel_ai);
250  ast_free(app_ai);
251  ast_free(appdata_ai);
252  ast_free(uniqueid_ai);
253  ast_free(linkedid_ai);
254  ast_free(userfield_ai);
255  ast_free(peer_ai);
256 
257  return;
258 }
const char * account_code
Definition: cel.h:161
const char * caller_id_name
Definition: cel.h:151
Helper struct for getting the fields out of a CEL event.
Definition: cel.h:136
const char * linked_id
Definition: cel.h:164
static ast_mutex_t tds_lock
Definition: cel_tds.c:100
const char * user_defined_name
Definition: cel.h:150
const char * application_data
Definition: cel.h:160
const char * application_name
Definition: cel.h:159
const char * extension
Definition: cel.h:156
const char * ast_channel_amaflags2string(enum ama_flags flags)
Convert the enum representation of an AMA flag to a string representation.
Definition: channel.c:4418
const char * caller_id_num
Definition: cel.h:152
#define ast_mutex_lock(a)
Definition: lock.h:187
static int mssql_disconnect(void)
Definition: cel_tds.c:336
int done
Definition: test_amihooks.c:48
#define ast_log
Definition: astobj2.c:42
const char * context
Definition: cel.h:157
uint32_t version
struct ABI version
Definition: cel.h:146
static struct cel_tds_config * settings
Definition: cel_tds.c:102
enum ast_cel_event_type event_type
Definition: cel.h:147
const ast_string_field connection
Definition: cel_tds.c:95
DBPROCESS * dbproc
Definition: cel_tds.c:96
#define LOG_ERROR
Definition: logger.h:285
const char * caller_id_rdnis
Definition: cel.h:154
static char * anti_injection(const char *, int)
Definition: cel_tds.c:260
const char * peer
Definition: cel.h:167
const ast_string_field table
Definition: cel_tds.c:95
#define LOG_NOTICE
Definition: logger.h:263
#define ast_free(a)
Definition: astmm.h:182
const char * caller_id_ani
Definition: cel.h:153
const char * user_field
Definition: cel.h:166
#define AST_CEL_EVENT_RECORD_VERSION
struct ABI version
Definition: cel.h:141
const char * unique_id
Definition: cel.h:163
static int mssql_connect(void)
Definition: cel_tds.c:347
a user-defined event, the event name field should be set
Definition: cel.h:69
const char * caller_id_dnid
Definition: cel.h:155
const char * channel_name
Definition: cel.h:158
static void get_date(char *, size_t len, struct timeval)
Definition: cel_tds.c:293
const char * event_name
Definition: cel.h:149
struct timeval event_time
Definition: cel.h:148
unsigned int connected
Definition: cel_tds.c:97
int ast_cel_fill_record(const struct ast_event *event, struct ast_cel_event_record *r)
Fill in an ast_cel_event_record from a CEL event.
Definition: cel.c:819
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ tds_message_handler()

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

References ast_debug, ast_log, and LOG_NOTICE.

Referenced by load_module().

426 {
427  ast_debug(1, "Msg %d, Level %d, State %d, Line %d\n", msgno, severity, msgstate, line);
428  ast_log(LOG_NOTICE, "%s\n", msgtext);
429 
430  return 0;
431 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define LOG_NOTICE
Definition: logger.h:263
enum ast_security_event_severity severity

◆ tds_unload_module()

static int tds_unload_module ( void  )
static

Definition at line 396 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.

Referenced by unload_module().

397 {
399 
400  if (settings) {
404 
407  }
408 
409  dbexit();
410 
411  return 0;
412 }
static ast_mutex_t tds_lock
Definition: cel_tds.c:100
#define TDS_BACKEND_NAME
Definition: cel_tds.c:82
#define ast_mutex_lock(a)
Definition: lock.h:187
static int mssql_disconnect(void)
Definition: cel_tds.c:336
static struct cel_tds_config * settings
Definition: cel_tds.c:102
int ast_cel_backend_unregister(const char *name)
Unregister a CEL backend.
Definition: cel.c:1728
#define ast_free(a)
Definition: astmm.h:182
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 572 of file cel_tds.c.

References AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CDR_DRIVER, AST_MODULE_INFO(), AST_MODULE_SUPPORT_EXTENDED, ASTERISK_GPL_KEY, load_module(), reload(), and tds_unload_module().

573 {
574  return tds_unload_module();
575 }
static int tds_unload_module(void)
Definition: cel_tds.c:396

Variable Documentation

◆ __mod_info

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, .requires = "cel", }
static

Definition at line 584 of file cel_tds.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 584 of file cel_tds.c.

◆ config

char* config = "cel_tds.conf"
static

Definition at line 84 of file cel_tds.c.

Referenced by tds_load_module().

◆ settings

struct cel_tds_config* settings
static

Definition at line 102 of file cel_tds.c.

◆ tds_lock

ast_mutex_t tds_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 100 of file cel_tds.c.

Referenced by tds_load_module(), tds_log(), and tds_unload_module().