Asterisk - The Open Source Telephony Project  18.5.0
cel_tds.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2008, Digium, Inc.
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16 
17 /*! \file
18  *
19  * \brief FreeTDS CEL logger
20  *
21  * See also
22  * \arg \ref Config_cel
23  * \arg http://www.freetds.org/
24  * \ingroup cel_drivers
25  */
26 
27 /*! \verbatim
28  *
29  * Table Structure for `cel`
30  *
31 
32 CREATE TABLE [dbo].[cel] (
33  [accountcode] [varchar] (20) NULL ,
34  [cidname] [varchar] (80) NULL ,
35  [cidnum] [varchar] (80) NULL ,
36  [cidani] [varchar] (80) NULL ,
37  [cidrdnis] [varchar] (80) NULL ,
38  [ciddnid] [varchar] (80) NULL ,
39  [exten] [varchar] (80) NULL ,
40  [context] [varchar] (80) NULL ,
41  [channame] [varchar] (80) NULL ,
42  [appname] [varchar] (80) NULL ,
43  [appdata] [varchar] (80) NULL ,
44  [eventtime] [datetime] NULL ,
45  [eventtype] [varchar] (32) NULL ,
46  [uniqueid] [varchar] (32) NULL ,
47  [linkedid] [varchar] (32) NULL ,
48  [amaflags] [varchar] (16) NULL ,
49  [userfield] [varchar] (32) NULL ,
50  [peer] [varchar] (32) NULL
51 ) ON [PRIMARY]
52 
53 \endverbatim
54 
55 */
56 
57 /*** MODULEINFO
58  <depend>freetds</depend>
59  <support_level>extended</support_level>
60  ***/
61 
62 #include "asterisk.h"
63 
64 #include <time.h>
65 #include <math.h>
66 
67 #include "asterisk/config.h"
68 #include "asterisk/channel.h"
69 #include "asterisk/cel.h"
70 #include "asterisk/module.h"
71 #include "asterisk/logger.h"
72 
73 #include <sqlfront.h>
74 #include <sybdb.h>
75 
76 #ifdef FREETDS_PRE_0_62
77 #warning "You have older TDS, you should upgrade!"
78 #endif
79 
80 #define DATE_FORMAT "%Y/%m/%d %T"
81 
82 #define TDS_BACKEND_NAME "CEL TDS logging backend"
83 
84 static char *config = "cel_tds.conf";
85 
95  );
96  DBPROCESS *dbproc;
97  unsigned int connected:1;
98 };
99 
101 
102 static struct cel_tds_config *settings;
103 
104 static char *anti_injection(const char *, int);
105 static void get_date(char *, size_t len, struct timeval);
106 
107 static int execute_and_consume(DBPROCESS *dbproc, const char *fmt, ...)
108  __attribute__((format(printf, 2, 3)));
109 
110 static int mssql_connect(void);
111 static int mssql_disconnect(void);
112 
113 static void tds_log(struct ast_event *event)
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 }
259 
260 static char *anti_injection(const char *str, int len)
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 }
292 
293 static void get_date(char *dateField, size_t len, struct timeval when)
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 }
304 
305 static int execute_and_consume(DBPROCESS *dbproc, const char *fmt, ...)
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 }
335 
336 static int mssql_disconnect(void)
337 {
338  if (settings->dbproc) {
339  dbclose(settings->dbproc);
340  settings->dbproc = NULL;
341  }
342  settings->connected = 0;
343 
344  return 0;
345 }
346 
347 static int mssql_connect(void)
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 
360  if (!ast_strlen_zero(settings->charset)) {
361  DBSETLCHARSET(login, (char *) settings->charset);
362  }
363 
364  if (!ast_strlen_zero(settings->language)) {
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 }
395 
396 static int tds_unload_module(void)
397 {
399 
400  if (settings) {
404 
406  ast_free(settings);
407  }
408 
409  dbexit();
410 
411  return 0;
412 }
413 
414 static int tds_error_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
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 }
424 
425 static int tds_message_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line)
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 }
432 
433 static int tds_load_module(int 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 */
457  ast_string_field_init(settings, 0);
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) {
485  ast_string_field_set(settings, password, 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) {
493  ast_string_field_set(settings, charset, ptr);
494  }
495 
496  ptr = ast_variable_retrieve(cfg, "global", "language");
497  if (ptr) {
498  ast_string_field_set(settings, language, ptr);
499  }
500 
501  ptr = ast_variable_retrieve(cfg, "global", "table");
502  if (ptr) {
503  ast_string_field_set(settings, table, ptr);
504  } else {
505  ast_log(LOG_NOTICE, "Table name not specified, using 'cel' by default.\n");
506  ast_string_field_set(settings, table, "cel");
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 }
527 
528 static int reload(void)
529 {
530  return tds_load_module(1);
531 }
532 
533 static int load_module(void)
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 
543  settings = ast_calloc_with_stringfields(1, struct cel_tds_config, 256);
544 
545  if (!settings) {
546  dbexit();
548  }
549 
550  if (!tds_load_module(0)) {
552  ast_free(settings);
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");
563  ast_free(settings);
564  settings = NULL;
565  dbexit();
567  }
568 
570 }
571 
572 static int unload_module(void)
573 {
574  return tds_unload_module();
575 }
576 
578  .support_level = AST_MODULE_SUPPORT_EXTENDED,
579  .load = load_module,
580  .unload = unload_module,
581  .reload = reload,
582  .load_pri = AST_MODPRI_CDR_DRIVER,
583  .requires = "cel",
584 );
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
An event.
Definition: event.c:81
Asterisk main include file. File version handling, generic pbx functions.
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
Call Event Logging API.
Time-related functions and macros.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
const char * user_defined_name
Definition: cel.h:150
const ast_string_field charset
Definition: cel_tds.c:95
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
const char * application_data
Definition: cel.h:160
#define DATE_FORMAT
Definition: cel_tds.c:80
const char * application_name
Definition: cel.h:159
#define TDS_BACKEND_NAME
Definition: cel_tds.c:82
#define CONFIG_STATUS_FILEINVALID
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
const char * extension
Definition: cel.h:156
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:426
Definition: astman.c:222
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
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:337
const char * caller_id_num
Definition: cel.h:152
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_vasprintf(ret, fmt, ap)
A wrapper for vasprintf()
Definition: astmm.h:280
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
static int mssql_disconnect(void)
Definition: cel_tds.c:336
const ast_string_field username
Definition: cel_tds.c:95
#define ast_strlen_zero(foo)
Definition: strings.h:52
int done
Definition: test_amihooks.c:48
Configuration File Parser.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
General Asterisk PBX channel definitions.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
static int execute_and_consume(DBPROCESS *dbproc, const char *fmt,...)
Definition: cel_tds.c:305
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:299
const char * context
Definition: cel.h:157
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
uint32_t version
struct ABI version
Definition: cel.h:146
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 CONFIG_STATUS_FILEUNCHANGED
static int tds_error_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
Definition: cel_tds.c:414
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 ast_string_field database
Definition: cel_tds.c:95
static int load_module(void)
Definition: cel_tds.c:533
const char * caller_id_rdnis
Definition: cel.h:154
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static char * anti_injection(const char *, int)
Definition: cel_tds.c:260
const char * peer
Definition: cel.h:167
static int unload_module(void)
Definition: cel_tds.c:572
const ast_string_field table
Definition: cel_tds.c:95
#define LOG_NOTICE
Definition: logger.h:263
char * strcasestr(const char *, const char *)
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
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
const char * caller_id_ani
Definition: cel.h:153
const ast_string_field password
Definition: cel_tds.c:95
const char * user_field
Definition: cel.h:166
charset
Definition: chan_unistim.c:336
#define AST_CEL_EVENT_RECORD_VERSION
struct ABI version
Definition: cel.h:141
Structure used to handle boolean flags.
Definition: utils.h:199
Support for logging to various files, console and syslog Configuration in file logger.conf.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
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
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int tds_load_module(int reload)
Definition: cel_tds.c:433
enum ast_security_event_severity severity
const char * unique_id
Definition: cel.h:163
static int mssql_connect(void)
Definition: cel_tds.c:347
static int tds_unload_module(void)
Definition: cel_tds.c:396
a user-defined event, the event name field should be set
Definition: cel.h:69
const ast_string_field language
Definition: cel_tds.c:95
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
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
static char * config
Definition: cel_tds.c:84
static snd_pcm_format_t format
Definition: chan_alsa.c:102
struct timeval event_time
Definition: cel.h:148
#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
unsigned int connected
Definition: cel_tds.c:97
DB * dbopen(char *fname, int flags, int mode, DBTYPE type, const void *openinfo) const
static void tds_log(struct ast_event *event)
Definition: cel_tds.c:113
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:518
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
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514