69 #include "asterisk/config.h"
77 #define DATE_FORMAT "%Y/%m/%d %T"
79 static const char name[] =
"FreeTDS (MSSQL)";
80 static const char config[] =
"cdr_tds.conf";
103 static void get_date(
char *,
size_t len,
struct timeval);
106 __attribute__((
format(printf, 2, 3)));
113 char start[80], answer[80], end[80];
114 char *
accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid, *userfield = NULL;
130 get_date(start,
sizeof(start), cdr->start);
131 get_date(answer,
sizeof(answer), cdr->answer);
132 get_date(end,
sizeof(end), cdr->end);
155 double hrbillsec = 0.0;
159 hrbillsec = (double)(
ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0);
161 hrduration = (double)(
ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0);
163 erc = dbfcmd(settings->
dbproc,
166 "accountcode, src, dst, dcontext, clid, channel, "
167 "dstchannel, lastapp, lastdata, start, answer, [end], duration, "
168 "billsec, disposition, amaflags, uniqueid, userfield"
172 "'%s', '%s', '%s', '%s', '%s', '%s', "
173 "'%s', '%s', '%s', %s, %s, %s, %lf, "
174 "%lf, '%s', '%s', '%s', '%s'"
177 accountcode, src, dst, dcontext, clid, channel,
178 dstchannel, lastapp, lastdata, start, answer, end, hrduration,
183 erc = dbfcmd(settings->
dbproc,
186 "accountcode, src, dst, dcontext, clid, channel, "
187 "dstchannel, lastapp, lastdata, start, answer, [end], duration, "
188 "billsec, disposition, amaflags, uniqueid, userfield"
192 "'%s', '%s', '%s', '%s', '%s', '%s', "
193 "'%s', '%s', '%s', %s, %s, %s, %ld, "
194 "%ld, '%s', '%s', '%s', '%s'"
197 accountcode, src, dst, dcontext, clid, channel,
198 dstchannel, lastapp, lastdata, start, answer, end, cdr->duration,
205 double hrbillsec = 0.0;
209 hrbillsec = (double)(
ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0);
211 hrduration = (double)(
ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0);
213 erc = dbfcmd(settings->
dbproc,
216 "accountcode, src, dst, dcontext, clid, channel, "
217 "dstchannel, lastapp, lastdata, start, answer, [end], duration, "
218 "billsec, disposition, amaflags, uniqueid"
222 "'%s', '%s', '%s', '%s', '%s', '%s', "
223 "'%s', '%s', '%s', %s, %s, %s, %lf, "
224 "%lf, '%s', '%s', '%s'"
227 accountcode, src, dst, dcontext, clid, channel,
228 dstchannel, lastapp, lastdata, start, answer, end, hrduration,
232 erc = dbfcmd(settings->
dbproc,
235 "accountcode, src, dst, dcontext, clid, channel, "
236 "dstchannel, lastapp, lastdata, start, answer, [end], duration, "
237 "billsec, disposition, amaflags, uniqueid"
241 "'%s', '%s', '%s', '%s', '%s', '%s', "
242 "'%s', '%s', '%s', %s, %s, %s, %ld, "
243 "%ld, '%s', '%s', '%s'"
246 accountcode, src, dst, dcontext, clid, channel,
247 dstchannel, lastapp, lastdata, start, answer, end, cdr->duration,
259 ast_log(
LOG_ERROR,
"Failed to build INSERT statement, no CDR was logged.\n");
264 if (dbsqlexec(settings->
dbproc) == FAIL) {
270 ast_log(
LOG_ERROR,
"Failed to execute INSERT statement, no CDR was logged.\n");
277 while (dbresults(settings->
dbproc) != NO_MORE_RESULTS) {
278 while (dbnextrow(settings->
dbproc) != NO_MORE_ROWS);
308 char *buf_ptr, *srh_ptr;
309 char *known_bad[] = {
"select",
"insert",
"update",
"delete",
"drop",
";",
"--",
"\0"};
320 for (; *str && strlen(buf) <
len; str++) {
329 for (idx = 0; *known_bad[idx]; idx++) {
330 while ((srh_ptr =
strcasestr(buf, known_bad[idx]))) {
331 memmove(srh_ptr, srh_ptr + strlen(known_bad[idx]), strlen(srh_ptr + strlen(known_bad[idx])) + 1);
338 static void get_date(
char *dateField,
size_t len,
struct timeval when)
362 if (dbfcmd(dbproc, buffer) == FAIL) {
369 if (dbsqlexec(dbproc) == FAIL) {
374 while (dbresults(dbproc) != NO_MORE_RESULTS) {
375 while (dbnextrow(dbproc) != NO_MORE_ROWS);
384 dbclose(settings->
dbproc);
397 if ((login = dblogin()) == NULL) {
402 DBSETLAPP(login,
"TSQL");
403 DBSETLUSER(login, (
char *) settings->
username);
404 DBSETLPWD(login, (
char *) settings->
password);
405 DBSETLCHARSET(login, (
char *) settings->
charset);
406 DBSETLNATLANG(login, (
char *) settings->
language);
408 if ((settings->
dbproc = dbopen(login, (
char *) settings->
hostname)) == NULL) {
416 if (dbuse(settings->
dbproc, (
char *) settings->
database) == FAIL) {
439 dbclose(settings->
dbproc);
466 if (oserr != DBNOERR) {
473 static int tds_message_handler(DBPROCESS *dbproc, DBINT msgno,
int msgstate,
int severity,
char *msgtext,
char *srvname,
char *procname,
int line)
475 ast_debug(1,
"Msg %d, Level %d, State %d, Line %d\n", msgno, severity, msgstate, line);
484 const char *ptr = NULL;
515 ast_log(
LOG_ERROR,
"Failed to connect: Database server connection not specified.\n");
540 ast_log(
LOG_ERROR,
"Failed to connect: Database password not specified.\n");
570 ast_log(
LOG_NOTICE,
"High Resolution Time not found, using integers for billsec and duration fields by default.\n");
static char accountcode[AST_MAX_ACCOUNT_CODE]
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
static char * anti_injection(const char *, int)
#define AST_MAX_USER_FIELD
#define ast_vasprintf(a, b, c)
static const char config[]
static int tds_log(struct ast_cdr *cdr)
const ast_string_field hostname
const ast_string_field table
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
static ast_mutex_t tds_lock
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
const ast_string_field hrtime
#define ast_mutex_lock(a)
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
char * ast_cdr_flags2str(int flags)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
const ast_string_field language
static int mssql_connect(void)
static int load_module(void)
static int mssql_disconnect(void)
#define ast_debug(level,...)
Log a DEBUG message.
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
static int execute_and_consume(DBPROCESS *dbproc, const char *fmt,...)
General Asterisk PBX channel definitions.
unsigned int has_userfield
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_config_load(filename, flags)
Load a config file.
#define AST_STRING_FIELD(name)
Declare a string field.
static char language[MAX_LANGUAGE]
Responsible for call detail data.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
static int tds_error_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
const ast_string_field username
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const ast_string_field password
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
const ast_string_field charset
const ast_string_field database
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...
Structure used to handle boolean flags.
static int unload_module(void)
enum ast_security_event_severity severity
static int tds_load_module(int reload)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
#define CONFIG_STATUS_FILEINVALID
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
char * strcasestr(const char *, const char *)
static snd_pcm_format_t format
static struct cdr_tds_config * settings
static int tds_message_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line)
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
char * ast_cdr_disp2str(int disposition)
Disposition to a string.
#define AST_MUTEX_DEFINE_STATIC(mutex)
void ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
static int tds_unload_module(void)
#define CONFIG_STATUS_FILEUNCHANGED
#define ast_mutex_unlock(a)
static char hostname[MAXHOSTNAMELEN]
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
static void get_date(char *, size_t len, struct timeval)