Beispiel #1
0
	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();
		}
	}
Beispiel #2
0
/*
 * 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;
}
Beispiel #3
0
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);
        }
}
Beispiel #4
0
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);
}
Beispiel #5
0
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;
}
Beispiel #6
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;
}
Beispiel #9
0
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;
}