SQLConn(Module* m, const SQLhost& hi) : mod(m), host(hi), login(NULL), sock(NULL), context(NULL) { if (OpenDB()) { std::string query("USE " + host.name); if (tds_submit_query(sock, query.c_str()) == TDS_SUCCEED) { if (tds_process_simple_query(sock) != TDS_SUCCEED) { LoggingMutex->Lock(); ServerInstance->Logs->Log("m_mssql",LOG_DEFAULT, "WARNING: Could not select database " + host.name + " for DB with id: " + host.id); LoggingMutex->Unlock(); CloseDB(); } } else { LoggingMutex->Lock(); ServerInstance->Logs->Log("m_mssql",LOG_DEFAULT, "WARNING: Could not select database " + host.name + " for DB with id: " + host.id); LoggingMutex->Unlock(); CloseDB(); } } else { LoggingMutex->Lock(); ServerInstance->Logs->Log("m_mssql",LOG_DEFAULT, "WARNING: Could not connect to DB with id: " + host.id); LoggingMutex->Unlock(); CloseDB(); } }
/* * pool_mbr_login open a single pool login, to be call at init time or * to reconnect. */ static TDSSOCKET * pool_mbr_login(TDS_POOL * pool) { TDSCONTEXT *context; TDSLOGIN *login; TDSSOCKET *tds; TDSCONNECTION *connection; int rc; char *query; char hostname[MAXHOSTNAMELEN]; login = tds_alloc_login(); tds_set_passwd(login, pool->password); tds_set_user(login, pool->user); tds_set_app(login, "tdspool"); #if HAVE_GETHOSTNAME if (gethostname(hostname, MAXHOSTNAMELEN) < 0) #endif tds_strlcpy(hostname, "tdspool", MAXHOSTNAMELEN); tds_set_host(login, hostname); tds_set_library(login, "TDS-Library"); tds_set_server(login, pool->server); tds_set_client_charset(login, "iso_1"); tds_set_language(login, "us_english"); tds_set_packet(login, 512); context = tds_alloc_context(NULL); tds = tds_alloc_socket(context, 512); connection = tds_read_config_info(tds, login, context->locale); if (!connection || tds_connect_and_login(tds, connection) != TDS_SUCCEED) { tds_free_socket(tds); tds_free_connection(connection); /* what to do? */ fprintf(stderr, "Could not open connection to server %s\n", pool->server); return NULL; } tds_free_connection(connection); /* * FIXME -- tds_connect_and_login no longer preallocates the in_buf need to * do something like what tds_read_packet does */ tds->in_buf = (unsigned char *) calloc(BLOCKSIZ, 1); if (pool->database && strlen(pool->database)) { query = (char *) malloc(strlen(pool->database) + 5); sprintf(query, "use %s", pool->database); rc = tds_submit_query(tds, query); free(query); if (rc != TDS_SUCCEED) { fprintf(stderr, "changing database failed\n"); return NULL; } if (tds_process_simple_query(tds) != TDS_SUCCEED) return NULL; } return tds; }
static void exec_query(const char *query) { if (tds_submit_query(tds, query) != TDS_SUCCEED || tds_process_simple_query(tds) != TDS_SUCCEED) { fprintf(stderr, "executing query failed\n"); exit(1); } }
static void unfinished_query_test(TDSSOCKET *tds) { int char_len; char *buf, *p; int i, len; union { TDS_USMALLINT si; TDS_UINT i; TDS_INT8 i8; char buf[8]; } conv; if (IS_TDS72_PLUS(tds->conn)) return; tds_init_write_buf(tds); /* try to build an invalid (unfinished) query split in two packets */ char_len = IS_TDS7_PLUS(tds->conn) ? 2 : 1; buf = calloc(1, tds->out_buf_max + 200); memset(buf, '-', tds->out_buf_max + 200); strcpy(buf + (tds->out_buf_max - 8) / char_len - strlen(select_query) + 1, select_query); memset(strchr(buf, 0), 0, 16); /* convert if needed */ len = strlen(buf); for (i = len; --i >= 0; ) { char c = buf[i]; buf[i * char_len + 0] = c; if (IS_TDS7_PLUS(tds->conn)) buf[i * char_len + 1] = 0; } len *= char_len; /* send the query using tds_put_int8, non allineati */ tds->out_flag = TDS_QUERY; if (tds_set_state(tds, TDS_WRITING) != TDS_WRITING) exit(1); p = buf; memcpy(conv.buf, p, 2); tds_put_smallint(tds, conv.si); p += 2; for (; p < buf + len; p += 8) { CHECK_TDS_EXTRA(tds); memcpy(conv.buf, p, 8); tds_put_int8(tds, conv.i8); } tds_flush_packet(tds); tds_set_state(tds, TDS_PENDING); /* check result was fine */ if (TDS_FAILED(tds_process_simple_query(tds))) { fprintf(stderr, "Error in prepared query\n"); exit(1); } free(buf); }
int main(int argc, char **argv) { TDSLOGIN *login; TDSSOCKET *tds; int verbose = 0; int rc; fprintf(stdout, "%s: Testing DB change -- 'use tempdb'\n", __FILE__); rc = try_tds_login(&login, &tds, __FILE__, verbose); if (rc != TDS_SUCCESS) { fprintf(stderr, "try_tds_login() failed\n"); return 1; } rc = tds_submit_query(tds, "use tempdb"); if (rc != TDS_SUCCESS) { fprintf(stderr, "tds_submit_query() failed\n"); return 1; } /* warning: this mucks with some internals to get the env chg message */ if (tds_process_simple_query(tds) != TDS_SUCCESS) { fprintf(stderr, "query results failed\n"); return 1; } if (!tds || !tds->conn->env.database) { fprintf(stderr, "No database ??\n"); return 1; } /* Test currently disabled during TDSENV changes */ if (verbose) { fprintf(stdout, "database changed to %s\n", tds->conn->env.database); } if (strcmp(tds->conn->env.database, "tempdb")) { fprintf(stderr, "Wrong database, %s != tempdb\n", tds->conn->env.database); return 1; } try_tds_logout(login, tds, verbose); return 0; }
int main(int argc, char **argv) { TDSLOGIN *login; TDSSOCKET *tds; int ret; int verbose = 0; TDS_INT8 i8; unsigned limit; fprintf(stdout, "%s: Testing login, logout\n", __FILE__); ret = try_tds_login(&login, &tds, __FILE__, verbose); if (ret != TDS_SUCCESS) { fprintf(stderr, "try_tds_login() failed\n"); return 1; } unfinished_query_test(tds); tds->out_flag = TDS_QUERY; if (tds_set_state(tds, TDS_WRITING) != TDS_WRITING) { return 1; } tds_put_n(tds, "aaa", 3); limit = tds->out_buf_max / 8 + 100; for (i8 = 0; i8 < limit; ++i8) { CHECK_TDS_EXTRA(tds); tds_put_int8(tds, i8); } tds_send_cancel(tds); tds_process_simple_query(tds); try_tds_logout(login, tds, verbose); return 0; }
static int mssql_connect(void) { #if (defined(FREETDS_0_63) || defined(FREETDS_0_64)) TDSCONNECTION *connection = NULL; #else TDSCONNECTINFO *connection = NULL; #endif char query[128]; /* Connect to M$SQL Server */ if (!(login = tds_alloc_login())) { ast_log(LOG_ERROR, "tds_alloc_login() failed.\n"); return -1; } tds_set_server(login, hostname); tds_set_user(login, dbuser); tds_set_passwd(login, password); tds_set_app(login, "TSQL"); tds_set_library(login, "TDS-Library"); #ifndef FREETDS_PRE_0_62 tds_set_client_charset(login, charset); #endif tds_set_language(login, language); tds_set_packet(login, 512); tds_set_version(login, 7, 0); #ifdef FREETDS_0_64 if (!(context = tds_alloc_context(NULL))) #else if (!(context = tds_alloc_context())) #endif { ast_log(LOG_ERROR, "tds_alloc_context() failed.\n"); goto connect_fail; } if (!(tds = tds_alloc_socket(context, 512))) { ast_log(LOG_ERROR, "tds_alloc_socket() failed.\n"); goto connect_fail; } tds_set_parent(tds, NULL); connection = tds_read_config_info(tds, login, context->locale); if (!connection) { ast_log(LOG_ERROR, "tds_read_config() failed.\n"); goto connect_fail; } if (tds_connect(tds, connection) == TDS_FAIL) { ast_log(LOG_ERROR, "Failed to connect to MSSQL server.\n"); tds = NULL; /* freed by tds_connect() on error */ #if (defined(FREETDS_0_63) || defined(FREETDS_0_64)) tds_free_connection(connection); #else tds_free_connect(connection); #endif connection = NULL; goto connect_fail; } #if (defined(FREETDS_0_63) || defined(FREETDS_0_64)) tds_free_connection(connection); #else tds_free_connect(connection); #endif connection = NULL; sprintf(query, "USE %s", dbname); #ifdef FREETDS_PRE_0_62 if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED)) #else if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED)) #endif { ast_log(LOG_ERROR, "Could not change database (%s)\n", dbname); goto connect_fail; } connected = 1; return 0; connect_fail: mssql_disconnect(); return -1; }
static int tds_log(struct ast_cdr *cdr) { char sqlcmd[2048], start[80], answer[80], end[80]; char *accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid; int res = 0; int retried = 0; #ifdef FREETDS_PRE_0_62 TDS_INT result_type; #endif ast_mutex_lock(&tds_lock); memset(sqlcmd, 0, 2048); accountcode = anti_injection(cdr->accountcode, 20); src = anti_injection(cdr->src, 80); dst = anti_injection(cdr->dst, 80); dcontext = anti_injection(cdr->dcontext, 80); clid = anti_injection(cdr->clid, 80); channel = anti_injection(cdr->channel, 80); dstchannel = anti_injection(cdr->dstchannel, 80); lastapp = anti_injection(cdr->lastapp, 80); lastdata = anti_injection(cdr->lastdata, 80); uniqueid = anti_injection(cdr->uniqueid, 32); get_date(start, cdr->start); get_date(answer, cdr->answer); get_date(end, cdr->end); sprintf( sqlcmd, "INSERT INTO cdr " "(" "accountcode, " "src, " "dst, " "dcontext, " "clid, " "channel, " "dstchannel, " "lastapp, " "lastdata, " "start, " "answer, " "[end], " "duration, " "billsec, " "disposition, " "amaflags, " "uniqueid" ") " "VALUES " "(" "'%s', " /* accountcode */ "'%s', " /* src */ "'%s', " /* dst */ "'%s', " /* dcontext */ "'%s', " /* clid */ "'%s', " /* channel */ "'%s', " /* dstchannel */ "'%s', " /* lastapp */ "'%s', " /* lastdata */ "%s, " /* start */ "%s, " /* answer */ "%s, " /* end */ "%ld, " /* duration */ "%ld, " /* billsec */ "'%s', " /* disposition */ "'%s', " /* amaflags */ "'%s'" /* uniqueid */ ")", accountcode, src, dst, dcontext, clid, channel, dstchannel, lastapp, lastdata, start, answer, end, cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid ); do { if (!connected) { if (mssql_connect()) ast_log(LOG_ERROR, "Failed to reconnect to SQL database.\n"); else ast_log(LOG_WARNING, "Reconnected to SQL database.\n"); retried = 1; /* note that we have now tried */ } #ifdef FREETDS_PRE_0_62 if (!connected || (tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED)) #else if (!connected || (tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED)) #endif { ast_log(LOG_ERROR, "Failed to insert Call Data Record into SQL database.\n"); mssql_disconnect(); /* this is ok even if we are already disconnected */ } } while (!connected && !retried); free(accountcode); free(src); free(dst); free(dcontext); free(clid); free(channel); free(dstchannel); free(lastapp); free(lastdata); free(uniqueid); ast_mutex_unlock(&tds_lock); return res; }
bool pool_user_send_login_ack(TDS_POOL * pool, TDS_POOL_USER * puser) { char msg[256]; char block[32]; TDSSOCKET *tds = puser->sock.tds, *mtds = puser->assigned_member->sock.tds; TDSLOGIN *login = puser->login; const char *database; const char *server = mtds->conn->server ? mtds->conn->server : "JDBC"; bool dbname_mismatch, odbc_mismatch; pool->user_logins++; /* copy a bit of information, resize socket with block */ tds->conn->tds_version = mtds->conn->tds_version; tds->conn->product_version = mtds->conn->product_version; memcpy(tds->conn->collation, mtds->conn->collation, sizeof(tds->conn->collation)); tds->conn->tds71rev1 = mtds->conn->tds71rev1; free(tds->conn->product_name); tds->conn->product_name = strdup(mtds->conn->product_name); tds_realloc_socket(tds, mtds->conn->env.block_size); tds->conn->env.block_size = mtds->conn->env.block_size; tds->conn->client_spid = mtds->conn->spid; /* if database is different use USE statement */ database = pool->database; dbname_mismatch = !tds_dstr_isempty(&login->database) && strcasecmp(tds_dstr_cstr(&login->database), database) != 0; odbc_mismatch = (login->option_flag2 & TDS_ODBC_ON) == 0; if (dbname_mismatch || odbc_mismatch) { char *str; int len = 128 + tds_quote_id(mtds, NULL, tds_dstr_cstr(&login->database),-1); TDSRET ret; if ((str = (char *) malloc(len)) == NULL) return false; str[0] = 0; /* swicth to dblib options */ if (odbc_mismatch) strcat(str, "SET ANSI_DEFAULTS OFF\nSET CONCAT_NULL_YIELDS_NULL OFF\n"); if (dbname_mismatch) { strcat(str, "USE "); tds_quote_id(mtds, strchr(str, 0), tds_dstr_cstr(&login->database), -1); } ret = tds_submit_query(mtds, str); free(str); if (TDS_FAILED(ret) || TDS_FAILED(tds_process_simple_query(mtds))) return false; if (dbname_mismatch) database = tds_dstr_cstr(&login->database); else database = mtds->conn->env.database; } // 7.0 // env database // database change message (with server name correct) // env language // language change message // env 0x3 charset ("iso_1") // env 0x5 lcid ("1033") // env 0x6 ("196609" ?? 0x30001) // loginack // env 0x4 packet size // done // // 7.1/7.2/7.3 // env database // database change message (with server name correct) // env 0x7 collation // env language // language change message // loginack // env 0x4 packet size // done tds->out_flag = TDS_REPLY; tds_env_change(tds, TDS_ENV_DATABASE, "master", database); sprintf(msg, "Changed database context to '%s'.", database); tds_send_msg(tds, 5701, 2, 0, msg, server, NULL, 1); if (!login->suppress_language) { tds_env_change(tds, TDS_ENV_LANG, NULL, "us_english"); tds_send_msg(tds, 5703, 1, 0, "Changed language setting to 'us_english'.", server, NULL, 1); } if (IS_TDS71_PLUS(tds->conn)) { tds_put_byte(tds, TDS_ENVCHANGE_TOKEN); tds_put_smallint(tds, 8); tds_put_byte(tds, TDS_ENV_SQLCOLLATION); tds_put_byte(tds, 5); tds_put_n(tds, tds->conn->collation, 5); tds_put_byte(tds, 0); } tds_send_login_ack(tds, mtds->conn->product_name); sprintf(block, "%d", tds->conn->env.block_size); tds_env_change(tds, TDS_ENV_PACKSIZE, block, block); /* tds_send_capabilities_token(tds); */ tds_send_done_token(tds, 0, 0); /* send it! */ tds_flush_packet(tds); tds_free_login(login); puser->login = NULL; return true; }