Skip to Content.
Sympa Menu

freetds - Re: [freetds] Dreaded "Server SYBASE not found!" question

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: Frediano Ziglio <freddy77 AT gmail.com>
  • To: FreeTDS Development Group <freetds AT lists.ibiblio.org>
  • Subject: Re: [freetds] Dreaded "Server SYBASE not found!" question
  • Date: Sun, 13 Dec 2009 09:23:13 +0100

Il giorno sab, 12/12/2009 alle 12.42 -0500, James K. Lowden ha scritto:
> Nelson, Erik - 2 wrote:
> > There's an outstanding todo in login.c to open the log file prior to
> > tds_set_server() where "SYBASE" is being set in to
> > connection->server_name, but it's not at all clear why the server
> > name/IP aren't being set correctly since the server info is clearly
> > being found in freetds.conf.
> ...
> > [Hiruko] found in "/modleng/usr/etc/odbc.ini"
> > found this section:
> > [Hiruko]
> > Driver = FreeTDS
> > Description = DataDirect 5.1 SQL Server Wire Protocol
> > Servername = Hiruko
> > Server = Hiruko
> > Port = 1433
>
> Server and Servername cannot be in the same section. One overrides the
> other.
>
> This highlights a more general question, for which I'd like to hear
> suggestions (and/or see a patch!) from anyone who's interested.
>
> We have two mutually exclusive attributes in our configuration files. In
> odbc.ini we have server/servername; in freetds.conf we have port/instance.
> These inevitably trip up some people, probably a lot more than write to
> the list, who over-specify the sever. What to do?
>
> One solution is to die noisily with err(3) when invalid combinations are
> found for the requested server. (Also, perhaps warnings writting to
> stderr for any other configuration problems e.g. invalid property names).
>
>
> A second way is to document the conflict clearly and have a careful
> override policy. I started working on that, but I'm not satisfied. It
> reminded me of something one of the Bell Labs guys said about writing
> early UNIX man pages: sometimes the documented behavior was so
> embarrassing that it motivated them to fix it.
>

I would suggest a proper error using correct way (that is no stderr).

> Another solution is to eliminate the "other" name.
>
> For odbc.ini, we could eliminate "servername". Instead, "server" would
> first be looked up in freetds.conf, if it exists. If nothing is found,
> then "server" would be treated as a DNS name. This is consistent with how
> a servername is treated during a db-lib/ct-lib lookup.

Although this breaks compatibility I'd agree. I see not that difference
between two terms.

> For freetds.conf, we could eliminate "instance" and always use "port". If
> "port" is a number, it's a port; if "port" is a string, it's a named
> instance. Or, always treat "port" as a potential named instance,
> interrogate the server, and revert to a number only if the server refuses
> to reply with a valid port. (I'm tempted to keep "instance" and eliminate
> "port" instead, but I'm held back, perhaps wrongly, by tradition. And I
> wonder whether you can name your instance "80"?)
>

And what about port is a port specified in /etc/services ?
Personally I would eliminate both and use "compressed" syntax like
"server:port" or "server\instance". This for two reason:
- is already supported by libTDS
- is compatible with ODBC and the way you specify this in DSN
configuration.

> I tend to favor "die early and often": if the configuration file is
> invalid, complain and stop. But, particularly in web environments (and
> given the way TDSDUMP logging works), it can be hard to diagnose why the
> server connection failed.
>

If upper layer do not read correctly error is not my problem.

> I *also* think it's better to make mistakes less likely by eliminating
> opportunities.
>

I think first step is eliminate confusion refusing to even try to
connect if both specified (server/servername and/or port/instance).

> Suggestions?
>

As a start see attached patch

freddy77

Index: include/tds.h
===================================================================
RCS file: /cvs/freetds/freetds/include/tds.h,v
retrieving revision 1.323
diff -U 10 -r1.323 tds.h
--- include/tds.h	26 Nov 2009 09:47:41 -0000	1.323
+++ include/tds.h	13 Dec 2009 08:13:56 -0000
@@ -280,21 +280,22 @@
  * TDSERRNO is emitted by libtds to the client library's error handler
  * (which may in turn call the client's error handler).
  * These match the db-lib msgno, because the same values have the same meaning
  * in db-lib and ODBC.  ct-lib maps them to ct-lib numbers (todo). 
  */
 typedef enum {	TDSEOK    = TDS_SUCCEED, 
 		TDSEICONVIU    = 2400, 
 		TDSEICONVAVAIL = 2401, 
 		TDSEICONVO     = 2402, 
 		TDSEICONVI     = 2403, 
-		TDSEICONV2BIG  = 2404, 
+		TDSEICONV2BIG  = 2404,
+		TDSEPORTINSTANCE	= 2500,
 		TDSESYNC = 20001, 
 		TDSEFCON = 20002, 
 		TDSETIME = 20003, 
 		TDSEREAD = 20004, 
 		TDSEWRIT = 20006, 
 		TDSESOCK = 20008, 
 		TDSECONN = 20009, 
 		TDSEMEM  = 20010,
 		TDSEINTF = 20012,	/* Server name not found in interface file */
 		TDSEUHST = 20013,	/* Unknown host machine name. */
Index: src/tds/config.c
===================================================================
RCS file: /cvs/freetds/freetds/src/tds/config.c,v
retrieving revision 1.151
diff -U 10 -r1.151 config.c
--- src/tds/config.c	26 Nov 2009 09:47:41 -0000	1.151
+++ src/tds/config.c	13 Dec 2009 08:13:56 -0000
@@ -619,24 +619,22 @@
 	}
 	if (login->suppress_language) {
 		connection->suppress_language = 1;
 	}
 	if (login->bulk_copy) {
 		connection->bulk_copy = 1;
 	}
 	if (login->block_size) {
 		connection->block_size = login->block_size;
 	}
-	if (login->port) {
+	if (login->port)
 		connection->port = login->port;
-		tds_dstr_copy(&connection->instance_name, "");
-	}
 	if (login->connect_timeout)
 		connection->connect_timeout = login->connect_timeout;
 
 	if (login->query_timeout)
 		connection->query_timeout = login->query_timeout;
 
 	/* copy other info not present in configuration file */
 	memcpy(connection->capabilities, login->capabilities, TDS_MAX_CAPABILITY);
 }
 
@@ -1029,25 +1027,21 @@
 
 		/*
 		 * Make a guess about the port number
 		 */
 
 		if (connection->port == 0) {
 			/*
 			 * Not set in the [global] section of the
 			 * configure file, take a guess.
 			 */
-#ifdef TDS50
-			ip_port = 4000;
-#else
-			ip_port = 1433;
-#endif
+			ip_port = TDS_DEF_PORT;
 		} else {
 			/*
 			 * Preserve setting from the [global] section
 			 * of the configure file.
 			 */
 			ip_port = connection->port;
 		}
 		if ((env_port = getenv("TDSPORT")) != NULL) {
 			ip_port = tds_lookup_port(env_port);
 			tdsdump_log(TDS_DBG_INFO1, "Setting 'ip_port' to %s from $TDSPORT.\n", env_port);
@@ -1080,28 +1074,26 @@
 	const char *pSep;
 	const char *server;
 
 	/* seek the ':' in login server_name */
 	server = tds_dstr_cstr(&login->server_name);
 	pSep = strrchr(server, ':');
 
 	if (pSep && pSep != server) {	/* yes, i found it! */
 		/* modify connection-> && login->server_name & ->port */
 		login->port = connection->port = atoi(pSep + 1);
-		tds_dstr_copy(&connection->instance_name, "");
 	} else {
 		/* handle instance name */
 		pSep = strrchr(server, '\\');
 		if (!pSep || pSep == server)
 			return 0;
 
-		login->port = connection->port = 0;
 		tds_dstr_copy(&connection->instance_name, pSep + 1);
 	}
 
 	tds_dstr_setlen(&login->server_name, pSep - server);
 	if (!tds_dstr_dup(&connection->server_name, &login->server_name))
 		return 0;
 
 	return 1;
 }
 
Index: src/tds/login.c
===================================================================
RCS file: /cvs/freetds/freetds/src/tds/login.c,v
retrieving revision 1.191
diff -U 10 -r1.191 login.c
--- src/tds/login.c	2 Dec 2009 22:58:21 -0000	1.191
+++ src/tds/login.c	13 Dec 2009 08:13:56 -0000
@@ -420,20 +420,25 @@
 		tdserror(tds->tds_ctx, tds, TDSEUHST, 0 );
 		tdsdump_log(TDS_DBG_ERROR, "IP address pointer is empty\n");
 		if (!tds_dstr_isempty(&connection->server_name)) {
 			tdsdump_log(TDS_DBG_ERROR, "Server %s not found!\n", tds_dstr_cstr(&connection->server_name));
 		} else {
 			tdsdump_log(TDS_DBG_ERROR, "No server specified!\n");
 		}
 		return TDSECONN;
 	}
 
+	if (connection->port && !tds_dstr_isempty(&connection->instance_name)) {
+		tdserror(tds->tds_ctx, tds, TDSEPORTINSTANCE, 0);
+		return TDSECONN;
+	}
+		
 	if (!IS_TDS50(tds) && !tds_dstr_isempty(&connection->instance_name))
 		connection->port = tds7_get_instance_port(tds_dstr_cstr(&connection->ip_addr), tds_dstr_cstr(&connection->instance_name));
 
 	if (connection->port < 1) {
 		tdsdump_log(TDS_DBG_ERROR, "invalid port number\n");
 		return TDSECONN;
 	}
 
 	memcpy(tds->capabilities, connection->capabilities, TDS_MAX_CAPABILITY);
 
Index: src/tds/mem.c
===================================================================
RCS file: /cvs/freetds/freetds/src/tds/mem.c,v
retrieving revision 1.193
diff -U 10 -r1.193 mem.c
--- src/tds/mem.c	26 Nov 2009 09:47:41 -0000	1.193
+++ src/tds/mem.c	13 Dec 2009 08:13:57 -0000
@@ -806,21 +806,20 @@
 	tds_dstr_init(&connection->ip_addr);
 	tds_dstr_init(&connection->database);
 	tds_dstr_init(&connection->dump_file);
 	tds_dstr_init(&connection->client_charset);
 	tds_dstr_init(&connection->instance_name);
 
 	/* fill in all hardcoded defaults */
 	if (!tds_dstr_copy(&connection->server_name, TDS_DEF_SERVER))
 		goto Cleanup;
 	connection->tds_version = TDS_DEFAULT_VERSION;
-	connection->port = TDS_DEF_PORT;
 	connection->block_size = 0;
 	/* TODO use system default ?? */
 	if (!tds_dstr_copy(&connection->client_charset, "ISO-8859-1"))
 		goto Cleanup;
 	if (locale) {
 		if (locale->language)
 			if (!tds_dstr_copy(&connection->language, locale->language))
 				goto Cleanup;
 		if (locale->server_charset)
 			if (!tds_dstr_copy(&connection->server_charset, locale->server_charset))
Index: src/tds/util.c
===================================================================
RCS file: /cvs/freetds/freetds/src/tds/util.c,v
retrieving revision 1.87
diff -U 10 -r1.87 util.c
--- src/tds/util.c	25 Aug 2009 14:25:35 -0000	1.87
+++ src/tds/util.c	13 Dec 2009 08:13:57 -0000
@@ -248,20 +248,21 @@
 
 static const TDS_ERROR_MESSAGE tds_error_messages[] = 
 	{ { TDSEICONVIU,     EXCONVERSION,	"Buffer exhausted converting characters from client into server's character set" }
 	, { TDSEICONVAVAIL,  EXCONVERSION,	"Character set conversion is not available between client character set '%.*s' and "
 						"server character set '%.*s'" }
 	, { TDSEICONVO,      EXCONVERSION,	"Error converting characters into server's character set. Some character(s) could "
 						"not be converted" }
 	, { TDSEICONVI,      EXCONVERSION,	"Some character(s) could not be converted into client's character set.  "
 						"Unconverted bytes were changed to question marks ('?')" }
 	, { TDSEICONV2BIG,   EXCONVERSION,	"Some character(s) could not be converted into client's character set" }
+	, { TDSEPORTINSTANCE,      EXCOMM,      "Both port and instance specified" }
 	, { TDSERPND,           EXPROGRAM,	"Attempt to initiate a new Adaptive Server operation with results pending" }
 	, { TDSEBTOK,              EXCOMM,	"Bad token from the server: Datastream processing out of sync" }
 	, { TDSECAP,               EXCOMM,	"DB-Library capabilities not accepted by the Server" }
 	, { TDSECAPTYP,            EXCOMM,	"Unexpected capability type in CAPABILITY datastream" }
 	, { TDSECLOS,              EXCOMM,	"Error in closing network connection" }
 	, { TDSECONN,              EXCOMM,	"Unable to connect: Adaptive Server is unavailable or does not exist" }
 	, { TDSEEUNR,              EXCOMM,	"Unsolicited event notification received" }
 	, { TDSEFCON,              EXCOMM,	"Adaptive Server connection failed" }
 	, { TDSENEG,               EXCOMM,	"Negotiated login attempt failed" }
 	, { TDSEOOB,               EXCOMM,	"Error in sending out-of-band data to the server" }



Archive powered by MHonArc 2.6.24.

Top of Page