Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
Data Structures | Macros | Functions | Variables
cdr_tds.c File Reference

FreeTDS CDR logger http://www.freetds.org/. 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>
Include dependency graph for cdr_tds.c:

Go to the source code of this file.

Data Structures

struct  cdr_tds_config
 

Macros

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

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static char * anti_injection (const char *, int)
 
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 int tds_log (struct ast_cdr *cdr)
 
static int tds_message_handler (DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line)
 
static int tds_unload_module (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "FreeTDS CDR Backend" , .key = ASTERISK_GPL_KEY , .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, .requires = "cdr", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const char config [] = "cdr_tds.conf"
 
static const char name [] = "FreeTDS (MSSQL)"
 
static struct cdr_tds_configsettings
 
static ast_mutex_t tds_lock = AST_MUTEX_INIT_VALUE
 

Detailed Description

FreeTDS CDR logger http://www.freetds.org/.

Definition in file cdr_tds.c.

Macro Definition Documentation

◆ DATE_FORMAT

#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 72 of file cdr_tds.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 636 of file cdr_tds.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 636 of file cdr_tds.c.

◆ anti_injection()

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

Definition at line 299 of file cdr_tds.c.

300{
301 /* Reference to http://www.nextgenss.com/papers/advanced_sql_injection.pdf */
302 char *buf;
303 char *buf_ptr, *srh_ptr;
304 char *known_bad[] = {"select", "insert", "update", "delete", "drop", ";", "--", "\0"};
305 int idx;
306
307 if (!(buf = ast_calloc(1, len + 1))) {
308 ast_log(LOG_ERROR, "Out of memory\n");
309 return NULL;
310 }
311
312 buf_ptr = buf;
313
314 /* Escape single quotes */
315 for (; *str && strlen(buf) < len; str++) {
316 if (*str == '\'') {
317 *buf_ptr++ = '\'';
318 }
319 *buf_ptr++ = *str;
320 }
321 *buf_ptr = '\0';
322
323 /* Erase known bad input */
324 for (idx = 0; *known_bad[idx]; idx++) {
325 while ((srh_ptr = strcasestr(buf, known_bad[idx]))) {
326 memmove(srh_ptr, srh_ptr + strlen(known_bad[idx]), strlen(srh_ptr + strlen(known_bad[idx])) + 1);
327 }
328 }
329
330 return buf;
331}
const char * str
Definition app_jack.c:150
char * strcasestr(const char *, const char *)
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define ast_log
Definition astobj2.c:42
char buf[BUFSIZE]
Definition eagi_proxy.c:66
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define LOG_ERROR
#define NULL
Definition resample.c:96

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

Referenced by tds_log().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 636 of file cdr_tds.c.

◆ execute_and_consume()

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

Definition at line 345 of file cdr_tds.c.

346{
347 va_list ap;
348 char *buffer;
349
350 va_start(ap, fmt);
351 if (ast_vasprintf(&buffer, fmt, ap) < 0) {
352 va_end(ap);
353 return 1;
354 }
355 va_end(ap);
356
357 if (dbfcmd(dbproc, buffer) == FAIL) {
358 ast_free(buffer);
359 return 1;
360 }
361
362 ast_free(buffer);
363
364 if (dbsqlexec(dbproc) == FAIL) {
365 return 1;
366 }
367
368 /* Consume the result set (we don't really care about the result, though) */
369 while (dbresults(dbproc) != NO_MORE_RESULTS) {
370 while (dbnextrow(dbproc) != NO_MORE_ROWS);
371 }
372
373 return 0;
374}
#define ast_free(a)
Definition astmm.h:180
#define ast_vasprintf(ret, fmt, ap)
A wrapper for vasprintf()
Definition astmm.h:278

References ast_free, and ast_vasprintf.

Referenced by mssql_connect().

◆ get_date()

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

Definition at line 333 of file cdr_tds.c.

334{
335 /* To make sure we have date variable if not insert null to SQL */
336 if (!ast_tvzero(when)) {
337 struct ast_tm tm;
338 ast_localtime(&when, &tm, NULL);
339 ast_strftime(dateField, len, "'" DATE_FORMAT "'", &tm);
340 } else {
341 ast_copy_string(dateField, "null", len);
342 }
343}
#define DATE_FORMAT
Definition cdr_tds.c:72
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_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:425
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition time.h:117

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

Referenced by tds_log().

◆ load_module()

static int load_module ( void  )
static

Definition at line 594 of file cdr_tds.c.

595{
596 if (dbinit() == FAIL) {
597 ast_log(LOG_ERROR, "Failed to initialize FreeTDS db-lib\n");
599 }
600
601 dberrhandle(tds_error_handler);
602 dbmsghandle(tds_message_handler);
603
605
606 if (!settings) {
607 dbexit();
609 }
610
611 if (!tds_load_module(0)) {
614 settings = NULL;
615 dbexit();
617 }
618
620
622}
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
Definition cdr.c:3076
static const char name[]
Definition cdr_tds.c:74
static int tds_log(struct ast_cdr *cdr)
Definition cdr_tds.c:106
static int tds_error_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
Definition cdr_tds.c:459
static struct cdr_tds_config * settings
Definition cdr_tds.c:95
static int tds_message_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line)
Definition cdr_tds.c:470
static int tds_load_module(int reload)
Definition cdr_tds.c:478
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition module.h:78
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
const char * description
Definition module.h:366

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, ast_module_info::description, LOG_ERROR, name, NULL, settings, tds_error_handler(), tds_load_module(), tds_log(), and tds_message_handler().

◆ mssql_connect()

static int mssql_connect ( void  )
static

Definition at line 388 of file cdr_tds.c.

389{
390 LOGINREC *login;
391
392 if ((login = dblogin()) == NULL) {
393 ast_log(LOG_ERROR, "Unable to allocate login structure for db-lib\n");
394 return -1;
395 }
396
397 DBSETLAPP(login, "TSQL");
398 DBSETLUSER(login, (char *) settings->username);
399 DBSETLPWD(login, (char *) settings->password);
400 DBSETLCHARSET(login, (char *) settings->charset);
401 DBSETLNATLANG(login, (char *) settings->language);
402
403 if ((settings->dbproc = dbopen(login, (char *) settings->hostname)) == NULL) {
404 ast_log(LOG_ERROR, "Unable to connect to %s\n", settings->hostname);
405 dbloginfree(login);
406 return -1;
407 }
408
409 dbloginfree(login);
410
411 if (dbuse(settings->dbproc, (char *) settings->database) == FAIL) {
412 ast_log(LOG_ERROR, "Unable to select database %s\n", settings->database);
413 goto failed;
414 }
415
416 if (execute_and_consume(settings->dbproc, "SELECT 1 FROM [%s] WHERE 1 = 0", settings->table)) {
417 ast_log(LOG_ERROR, "Unable to find table '%s'\n", settings->table);
418 goto failed;
419 }
420
421 /* Check to see if we have a userfield column in the table */
422 if (execute_and_consume(settings->dbproc, "SELECT userfield FROM [%s] WHERE 1 = 0", settings->table)) {
423 ast_log(LOG_NOTICE, "Unable to find 'userfield' column in table '%s'\n", settings->table);
425 } else {
427 }
428
429 settings->connected = 1;
430
431 return 0;
432
433failed:
434 dbclose(settings->dbproc);
436 return -1;
437}
static int execute_and_consume(DBPROCESS *dbproc, const char *fmt,...)
Definition cdr_tds.c:345
#define LOG_NOTICE
DBPROCESS * dbproc
Definition cdr_tds.c:88
const ast_string_field charset
Definition cdr_tds.c:87
const ast_string_field language
Definition cdr_tds.c:87
const ast_string_field database
Definition cdr_tds.c:87
const ast_string_field password
Definition cdr_tds.c:87
const ast_string_field username
Definition cdr_tds.c:87
const ast_string_field table
Definition cdr_tds.c:87
unsigned int connected
Definition cdr_tds.c:89
unsigned int has_userfield
Definition cdr_tds.c:90
const ast_string_field hostname
Definition cdr_tds.c:87

References ast_log, cdr_tds_config::charset, cdr_tds_config::connected, cdr_tds_config::database, cdr_tds_config::dbproc, execute_and_consume(), cdr_tds_config::has_userfield, cdr_tds_config::hostname, cdr_tds_config::language, LOG_ERROR, LOG_NOTICE, NULL, cdr_tds_config::password, settings, cdr_tds_config::table, and cdr_tds_config::username.

Referenced by tds_load_module(), and tds_log().

◆ mssql_disconnect()

static int mssql_disconnect ( void  )
static

Definition at line 376 of file cdr_tds.c.

377{
378 if (settings->dbproc) {
379 dbclose(settings->dbproc);
381 }
382
383 settings->connected = 0;
384
385 return 0;
386}

References cdr_tds_config::connected, cdr_tds_config::dbproc, NULL, and settings.

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

◆ reload()

static int reload ( void  )
static

Definition at line 589 of file cdr_tds.c.

590{
591 return tds_load_module(1);
592}

References tds_load_module().

Referenced by tds_load_module().

◆ tds_error_handler()

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

Definition at line 459 of file cdr_tds.c.

460{
461 ast_log(LOG_ERROR, "%s (%d)\n", dberrstr, dberr);
462
463 if (oserr != DBNOERR) {
464 ast_log(LOG_ERROR, "%s (%d)\n", oserrstr, oserr);
465 }
466
467 return INT_CANCEL;
468}

References ast_log, and LOG_ERROR.

Referenced by load_module().

◆ tds_load_module()

static int tds_load_module ( int  reload)
static

Definition at line 478 of file cdr_tds.c.

479{
480 struct ast_config *cfg;
481 const char *ptr = NULL;
482 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
483
484 cfg = ast_config_load(config, config_flags);
485 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
486 ast_log(LOG_NOTICE, "Unable to load TDS config for CDRs: %s\n", config);
487 return 0;
488 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
489 return 0;
490
491 if (!ast_variable_browse(cfg, "global")) {
492 /* nothing configured */
494 return 0;
495 }
496
498
499 /* Clear out any existing settings */
501
502 /* 'connection' is the new preferred configuration option */
503 ptr = ast_variable_retrieve(cfg, "global", "connection");
504 if (ptr) {
506 } else {
507 /* But we keep 'hostname' for backwards compatibility */
508 ptr = ast_variable_retrieve(cfg, "global", "hostname");
509 if (ptr) {
511 } else {
512 ast_log(LOG_ERROR, "Failed to connect: Database server connection not specified.\n");
513 goto failed;
514 }
515 }
516
517 ptr = ast_variable_retrieve(cfg, "global", "dbname");
518 if (ptr) {
519 ast_string_field_set(settings, database, ptr);
520 } else {
521 ast_log(LOG_ERROR, "Failed to connect: Database dbname not specified.\n");
522 goto failed;
523 }
524
525 ptr = ast_variable_retrieve(cfg, "global", "user");
526 if (ptr) {
527 ast_string_field_set(settings, username, ptr);
528 } else {
529 ast_log(LOG_ERROR, "Failed to connect: Database dbuser not specified.\n");
530 goto failed;
531 }
532
533 ptr = ast_variable_retrieve(cfg, "global", "password");
534 if (ptr) {
535 ast_string_field_set(settings, password, ptr);
536 } else {
537 ast_log(LOG_ERROR, "Failed to connect: Database password not specified.\n");
538 goto failed;
539 }
540
541 ptr = ast_variable_retrieve(cfg, "global", "charset");
542 if (ptr) {
544 } else {
546 }
547
548 ptr = ast_variable_retrieve(cfg, "global", "language");
549 if (ptr) {
551 } else {
552 ast_string_field_set(settings, language, "us_english");
553 }
554
555 ptr = ast_variable_retrieve(cfg, "global", "table");
556 if (ptr) {
557 ast_string_field_set(settings, table, ptr);
558 } else {
559 ast_log(LOG_NOTICE, "Table name not specified, using 'cdr' by default.\n");
560 ast_string_field_set(settings, table, "cdr");
561 }
562
563 ptr = ast_variable_retrieve(cfg, "global", "hrtime");
564 if (ptr && ast_true(ptr)) {
565 ast_string_field_set(settings, hrtime, ptr);
566 } else {
567 ast_log(LOG_NOTICE, "High Resolution Time not found, using integers for billsec and duration fields by default.\n");
568 }
569
571
572 if (mssql_connect()) {
573 /* We failed to connect (mssql_connect takes care of logging it) */
574 goto failed;
575 }
576
579
580 return 1;
581
582failed:
585
586 return 0;
587}
static int mssql_connect(void)
Definition cdr_tds.c:388
static const char config[]
Definition cdr_tds.c:75
static ast_mutex_t tds_lock
Definition cdr_tds.c:93
static int mssql_disconnect(void)
Definition cdr_tds.c:376
static int reload(void)
Definition cdr_tds.c:589
static char language[MAX_LANGUAGE]
Definition chan_iax2.c:348
charset
#define ast_config_load(filename, flags)
Load a config file.
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
@ CONFIG_FLAG_FILEUNCHANGED
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition extconf.c:1213
#define ast_mutex_unlock(a)
Definition lock.h:197
#define ast_mutex_lock(a)
Definition lock.h:196
static char hostname[MAXHOSTNAMELEN]
Definition logger.c:116
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition utils.c:2235
Structure used to handle boolean flags.
Definition utils.h:220

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(), config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, hostname, language, LOG_ERROR, LOG_NOTICE, mssql_connect(), mssql_disconnect(), NULL, reload(), settings, and tds_lock.

Referenced by load_module(), and reload().

◆ tds_log()

static int tds_log ( struct ast_cdr cdr)
static

Definition at line 106 of file cdr_tds.c.

107{
108 char start[80], answer[80], end[80];
109 char *accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid, *userfield = NULL;
110 RETCODE erc;
111 int res = -1;
112 int attempt = 1;
113
115 src = anti_injection(cdr->src, 80);
116 dst = anti_injection(cdr->dst, 80);
117 dcontext = anti_injection(cdr->dcontext, 80);
118 clid = anti_injection(cdr->clid, 80);
119 channel = anti_injection(cdr->channel, 80);
120 dstchannel = anti_injection(cdr->dstchannel, 80);
121 lastapp = anti_injection(cdr->lastapp, 80);
122 lastdata = anti_injection(cdr->lastdata, 80);
123 uniqueid = anti_injection(cdr->uniqueid, 32);
124
125 get_date(start, sizeof(start), cdr->start);
126 get_date(answer, sizeof(answer), cdr->answer);
127 get_date(end, sizeof(end), cdr->end);
128
130
131 if (settings->has_userfield) {
133 }
134
135retry:
136 /* Ensure that we are connected */
137 if (!settings->connected) {
138 ast_log(LOG_NOTICE, "Attempting to reconnect to %s (Attempt %d)\n", settings->hostname, attempt);
139 if (mssql_connect()) {
140 /* Connect failed */
141 if (attempt++ < 3) {
142 goto retry;
143 }
144 goto done;
145 }
146 }
147
148 if (settings->has_userfield) {
149 if (settings->hrtime) {
150 double hrbillsec = 0.0;
151 double hrduration;
152
153 if (!ast_tvzero(cdr->answer)) {
154 hrbillsec = (double)(ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0);
155 }
156 hrduration = (double)(ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0);
157
158 erc = dbfcmd(settings->dbproc,
159 "INSERT INTO %s "
160 "("
161 "accountcode, src, dst, dcontext, clid, channel, "
162 "dstchannel, lastapp, lastdata, start, answer, [end], duration, "
163 "billsec, disposition, amaflags, uniqueid, userfield"
164 ") "
165 "VALUES "
166 "("
167 "'%s', '%s', '%s', '%s', '%s', '%s', "
168 "'%s', '%s', '%s', %s, %s, %s, %lf, "
169 "%lf, '%s', '%s', '%s', '%s'"
170 ")",
172 accountcode, src, dst, dcontext, clid, channel,
173 dstchannel, lastapp, lastdata, start, answer, end, hrduration,
174 hrbillsec, ast_cdr_disp2str(cdr->disposition), ast_channel_amaflags2string(cdr->amaflags), uniqueid,
175 userfield
176 );
177 } else {
178 erc = dbfcmd(settings->dbproc,
179 "INSERT INTO %s "
180 "("
181 "accountcode, src, dst, dcontext, clid, channel, "
182 "dstchannel, lastapp, lastdata, start, answer, [end], duration, "
183 "billsec, disposition, amaflags, uniqueid, userfield"
184 ") "
185 "VALUES "
186 "("
187 "'%s', '%s', '%s', '%s', '%s', '%s', "
188 "'%s', '%s', '%s', %s, %s, %s, %ld, "
189 "%ld, '%s', '%s', '%s', '%s'"
190 ")",
192 accountcode, src, dst, dcontext, clid, channel,
193 dstchannel, lastapp, lastdata, start, answer, end, cdr->duration,
195 userfield
196 );
197 }
198 } else {
199 if (settings->hrtime) {
200 double hrbillsec = 0.0;
201 double hrduration;
202
203 if (!ast_tvzero(cdr->answer)) {
204 hrbillsec = (double)(ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0);
205 }
206 hrduration = (double)(ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0);
207
208 erc = dbfcmd(settings->dbproc,
209 "INSERT INTO %s "
210 "("
211 "accountcode, src, dst, dcontext, clid, channel, "
212 "dstchannel, lastapp, lastdata, start, answer, [end], duration, "
213 "billsec, disposition, amaflags, uniqueid"
214 ") "
215 "VALUES "
216 "("
217 "'%s', '%s', '%s', '%s', '%s', '%s', "
218 "'%s', '%s', '%s', %s, %s, %s, %lf, "
219 "%lf, '%s', '%s', '%s'"
220 ")",
222 accountcode, src, dst, dcontext, clid, channel,
223 dstchannel, lastapp, lastdata, start, answer, end, hrduration,
224 hrbillsec, ast_cdr_disp2str(cdr->disposition), ast_channel_amaflags2string(cdr->amaflags), uniqueid
225 );
226 } else {
227 erc = dbfcmd(settings->dbproc,
228 "INSERT INTO %s "
229 "("
230 "accountcode, src, dst, dcontext, clid, channel, "
231 "dstchannel, lastapp, lastdata, start, answer, [end], duration, "
232 "billsec, disposition, amaflags, uniqueid"
233 ") "
234 "VALUES "
235 "("
236 "'%s', '%s', '%s', '%s', '%s', '%s', "
237 "'%s', '%s', '%s', %s, %s, %s, %ld, "
238 "%ld, '%s', '%s', '%s'"
239 ")",
241 accountcode, src, dst, dcontext, clid, channel,
242 dstchannel, lastapp, lastdata, start, answer, end, cdr->duration,
244 );
245 }
246 }
247
248 if (erc == FAIL) {
249 if (attempt++ < 3) {
250 ast_log(LOG_NOTICE, "Failed to build INSERT statement, retrying...\n");
252 goto retry;
253 } else {
254 ast_log(LOG_ERROR, "Failed to build INSERT statement, no CDR was logged.\n");
255 goto done;
256 }
257 }
258
259 if (dbsqlexec(settings->dbproc) == FAIL) {
260 if (attempt++ < 3) {
261 ast_log(LOG_NOTICE, "Failed to execute INSERT statement, retrying...\n");
263 goto retry;
264 } else {
265 ast_log(LOG_ERROR, "Failed to execute INSERT statement, no CDR was logged.\n");
266 goto done;
267 }
268 }
269
270 /* Consume any results we might get back (this is more of a sanity check than
271 * anything else, since an INSERT shouldn't return results). */
272 while (dbresults(settings->dbproc) != NO_MORE_RESULTS) {
273 while (dbnextrow(settings->dbproc) != NO_MORE_ROWS);
274 }
275
276 res = 0;
277
278done:
280
282 ast_free(src);
283 ast_free(dst);
284 ast_free(dcontext);
285 ast_free(clid);
286 ast_free(channel);
287 ast_free(dstchannel);
288 ast_free(lastapp);
289 ast_free(lastdata);
290 ast_free(uniqueid);
291
292 if (userfield) {
293 ast_free(userfield);
294 }
295
296 return res;
297}
const char * ast_cdr_disp2str(int disposition)
Disposition to a string.
Definition cdr.c:3576
static char * anti_injection(const char *, int)
Definition cdr_tds.c:299
static void get_date(char *, size_t len, struct timeval)
Definition cdr_tds.c:333
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition chan_iax2.c:497
static int answer(void *data)
Definition chan_pjsip.c:687
const char * ast_channel_amaflags2string(enum ama_flags flags)
Convert the enum representation of an AMA flag to a string representation.
Definition channel.c:4367
#define AST_MAX_USER_FIELD
Definition channel.h:176
char * end
Definition eagi_proxy.c:73
char dstchannel[AST_MAX_EXTENSION]
Definition cdr.h:293
long int disposition
Definition cdr.h:309
char lastdata[AST_MAX_EXTENSION]
Definition cdr.h:297
char userfield[AST_MAX_USER_FIELD]
Definition cdr.h:327
long int billsec
Definition cdr.h:307
struct timeval answer
Definition cdr.h:301
char channel[AST_MAX_EXTENSION]
Definition cdr.h:291
long int duration
Definition cdr.h:305
long int amaflags
Definition cdr.h:311
char src[AST_MAX_EXTENSION]
Definition cdr.h:285
char dst[AST_MAX_EXTENSION]
Definition cdr.h:287
char clid[AST_MAX_EXTENSION]
Definition cdr.h:283
char uniqueid[AST_MAX_UNIQUEID]
Definition cdr.h:319
struct timeval start
Definition cdr.h:299
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition cdr.h:313
char lastapp[AST_MAX_EXTENSION]
Definition cdr.h:295
char dcontext[AST_MAX_EXTENSION]
Definition cdr.h:289
struct timeval end
Definition cdr.h:303
const ast_string_field hrtime
Definition cdr_tds.c:87
int done
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition time.h:87

References accountcode, answer(), anti_injection(), ast_cdr_disp2str(), ast_channel_amaflags2string(), 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, done, end, get_date(), cdr_tds_config::has_userfield, cdr_tds_config::hostname, cdr_tds_config::hrtime, LOG_ERROR, LOG_NOTICE, mssql_connect(), mssql_disconnect(), NULL, settings, cdr_tds_config::table, and tds_lock.

Referenced by load_module().

◆ 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 470 of file cdr_tds.c.

471{
472 ast_debug(1, "Msg %d, Level %d, State %d, Line %d\n", msgno, severity, msgstate, line);
473 ast_log(LOG_NOTICE, "%s\n", msgtext);
474
475 return 0;
476}
#define ast_debug(level,...)
Log a DEBUG message.
enum ast_security_event_severity severity

References ast_debug, ast_log, LOG_NOTICE, and severity.

Referenced by load_module().

◆ tds_unload_module()

static int tds_unload_module ( void  )
static

Definition at line 439 of file cdr_tds.c.

440{
442 return -1;
443 }
444
445 if (settings) {
449
452 }
453
454 dbexit();
455
456 return 0;
457}
int ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition cdr.c:3121

References ast_cdr_unregister(), ast_free, ast_mutex_lock, ast_mutex_unlock, ast_string_field_free_memory, mssql_disconnect(), name, settings, and tds_lock.

Referenced by unload_module().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 624 of file cdr_tds.c.

625{
626 return tds_unload_module();
627}
static int tds_unload_module(void)
Definition cdr_tds.c:439

References tds_unload_module().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "FreeTDS CDR Backend" , .key = ASTERISK_GPL_KEY , .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, .requires = "cdr", }
static

Definition at line 636 of file cdr_tds.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 636 of file cdr_tds.c.

◆ config

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

Definition at line 75 of file cdr_tds.c.

Referenced by tds_load_module().

◆ name

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

Definition at line 74 of file cdr_tds.c.

Referenced by load_module(), and tds_unload_module().

◆ settings

struct cdr_tds_config* settings
static

◆ tds_lock

ast_mutex_t tds_lock = AST_MUTEX_INIT_VALUE
static

Definition at line 93 of file cdr_tds.c.

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