Example #1
0
/**
 * Returns the version of the TDS protocol in effect for the link
 * as a decimal integer.  
 *	Typical returned values are 42, 50, 70, 80.
 * Also fills pversion_string unless it is null.
 * 	Typical pversion_string values are "4.2" and "7.0".
 */
static int
tds_version(TDSCONNECTION * conn, char *pversion_string)
{
	int iversion = 0;

	iversion = 10 * TDS_MAJOR(conn) + TDS_MINOR(conn);

	sprintf(pversion_string, "%d.%d", TDS_MAJOR(conn), TDS_MINOR(conn));

	return iversion;
}
Example #2
0
/**
 * Send any tokens that mark the start of a table.  This automatically chooses
 * the right tokens for this client's version of the TDS protocol.  In other
 * words, it is a wrapper around tds_send_col_name(), tds_send_col_info(),
 * tds_send_result(), and tds7_send_result().
 * \param tds		The socket to which the tokens will be written.  Also,
 *			it contains the TDS protocol version number.
 * \param resinfo	Describes the table to be send, especially the number
 *			of columns and the names & data types of each column.
 */
void tds_send_table_header(TDSSOCKET * tds, TDSRESULTINFO * resinfo)
{
	switch (TDS_MAJOR(tds->conn)) {
	case 4:
		/*
		 * TDS4 uses TDS_COLNAME_TOKEN to send column names, and
		 * TDS_COLFMT_TOKEN to send column info.  The number of columns
		 * is implied by the number of column names.
		 */
		tds_send_col_name(tds, resinfo);
		tds_send_col_info(tds, resinfo);
		break;

	case 5:
		/* TDS5 uses a TDS_RESULT_TOKEN to send all column information */
		tds_send_result(tds, resinfo);
		break;

	case 7:
		/*
		 * TDS7+ uses a TDS7_RESULT_TOKEN to send all column
		 * information.
		 */
		tds7_send_result(tds, resinfo);
		break;
	}
}
Example #3
0
void
tds_send_login_ack(TDSSOCKET * tds, const char *progname)
{
	TDS_UINT ui, version;

	tds_put_byte(tds, TDS_LOGINACK_TOKEN);
	tds_put_smallint(tds, 10 + (IS_TDS7_PLUS(tds->conn)? 2 : 1) * strlen(progname));	/* length of message */
	if (IS_TDS50(tds->conn)) {
		tds_put_byte(tds, 5);
		version = 0x05000000u;
	} else {
		tds_put_byte(tds, 1);
		/* see src/tds/token.c */
		if (IS_TDS73_PLUS(tds->conn)) {
			version = 0x730B0003u;
		} else if (IS_TDS72_PLUS(tds->conn)) {
			version = 0x72090002u;
		} else if (IS_TDS71_PLUS(tds->conn)) {
			version = tds->conn->tds71rev1 ? 0x07010000u : 0x71000001u;
		} else {
			version = (TDS_MAJOR(tds->conn) << 24) | (TDS_MINOR(tds->conn) << 16);
		}
	}
	TDS_PUT_A4BE(&ui, version);
	tds_put_n(tds, &ui, 4);

	tds_put_byte(tds, strlen(progname));
	/* FIXME ucs2 */
	tds_put_string(tds, progname, strlen(progname));

	/* server version, always big endian */
	TDS_PUT_A4BE(&ui, tds->conn->product_version & 0x7fffffffu);
	tds_put_n(tds, &ui, 4);
}
Example #4
0
static BOOL
write_all_strings(DSNINFO * di)
{
	char odbcini[FILENAME_MAX];
	char tmp[100];
	const char *section = tds_dstr_cstr(&di->dsn);

	strcpy(odbcini, "odbc.ini");

	WRITESTR("Server", FIELD_STRING(server_name));
	WRITESTR("Language", FIELD_STRING(language));
	WRITESTR("Database", FIELD_STRING(database));

	sprintf(tmp, "%u", di->login->port);
	WRITESTR("Port", tmp);

	sprintf(tmp, "%d.%d", TDS_MAJOR(di->login), TDS_MINOR(di->login));
	WRITESTR("TDS_Version", tmp);

	sprintf(tmp, "%u", di->login->text_size);
	WRITESTR("TextSize", tmp);

	sprintf(tmp, "%u", di->login->block_size);
	WRITESTR("PacketSize", tmp);

	return TRUE;
}
void
tds_send_login_ack(TDSSOCKET * tds, const char *progname)
{
	tds_put_byte(tds, TDS_LOGINACK_TOKEN);
	tds_put_smallint(tds, 10 + (IS_TDS7_PLUS(tds->conn)? 2 : 1) * strlen(progname));	/* length of message */
	if (IS_TDS50(tds->conn)) {
		tds_put_byte(tds, 5);
		tds_put_byte(tds, 5);
		tds_put_byte(tds, 0);
	} else {
		tds_put_byte(tds, 1);
		tds_put_byte(tds, TDS_MAJOR(tds->conn));
		tds_put_byte(tds, TDS_MINOR(tds->conn));
	}
	tds_put_byte(tds, 0);	/* unknown */
	tds_put_byte(tds, 0);	/* unknown */
	tds_put_byte(tds, strlen(progname));
	/* FIXME ucs2 */
	tds_put_string(tds, progname, strlen(progname));
	/* server version, for mssql 1.0.1 */
	tds_put_byte(tds, 1);	/* unknown */
	tds_put_byte(tds, 0);	/* unknown */
	tds_put_byte(tds, 0);	/* unknown */
	tds_put_byte(tds, 1);	/* unknown */
}
Example #6
0
void
dump_login(TDSLOGIN * login)
{
	fprintf(stderr, "host %s\n", tds_dstr_cstr(&login->client_host_name));
	fprintf(stderr, "user %s\n", tds_dstr_cstr(&login->user_name));
	fprintf(stderr, "pass %s\n", tds_dstr_cstr(&login->password));
	fprintf(stderr, "app  %s\n", tds_dstr_cstr(&login->app_name));
	fprintf(stderr, "srvr %s\n", tds_dstr_cstr(&login->server_name));
	fprintf(stderr, "vers %d.%d\n", TDS_MAJOR(login), TDS_MINOR(login));
	fprintf(stderr, "lib  %s\n", tds_dstr_cstr(&login->library));
	fprintf(stderr, "lang %s\n", tds_dstr_cstr(&login->language));
	fprintf(stderr, "char %s\n", tds_dstr_cstr(&login->server_charset));
	fprintf(stderr, "bsiz %d\n", login->block_size);
}
Example #7
0
/**
 * tds_read_config_info() will fill the tds connection structure based on configuration 
 * information gathered in the following order:
 * 1) Program specified in TDSLOGIN structure
 * 2) The environment variables TDSVER, TDSDUMP, TDSPORT, TDSQUERY, TDSHOST
 * 3) A config file with the following search order:
 *    a) a readable file specified by environment variable FREETDSCONF
 *    b) a readable file in ~/.freetds.conf
 *    c) a readable file in $prefix/etc/freetds.conf
 * 3) ~/.interfaces if exists
 * 4) $SYBASE/interfaces if exists
 * 5) TDS_DEF_* default values
 *
 * .tdsrc and freetds.conf have been added to make the package easier to 
 * integration with various Linux and *BSD distributions.
 */
TDSLOGIN *
tds_read_config_info(TDSSOCKET * tds, TDSLOGIN * login, TDSLOCALE * locale)
{
	TDSLOGIN *connection;
	char *s;
	char *path;
	pid_t pid;
	int opened = 0, found;
	struct addrinfo *addrs;

	/* allocate a new structure with hard coded and build-time defaults */
	connection = tds_alloc_login(0);
	if (!connection || !tds_init_login(connection, locale)) {
		tds_free_login(connection);
		return NULL;
	}

	s = getenv("TDSDUMPCONFIG");
	if (s) {
		if (*s) {
			opened = tdsdump_open(s);
		} else {
			pid = getpid();
			if (asprintf(&path, pid_config_logpath, pid) >= 0) {
				if (*path) {
					opened = tdsdump_open(path);
				}
				free(path);
			}
		}
	}

	tdsdump_log(TDS_DBG_INFO1, "Getting connection information for [%s].\n", 
			    tds_dstr_cstr(&login->server_name));	/* (The server name is set in login.c.) */

	/* Read the config files. */
	tdsdump_log(TDS_DBG_INFO1, "Attempting to read conf files.\n");
	found = tds_read_conf_file(connection, tds_dstr_cstr(&login->server_name));
	if (!found) {
		if (parse_server_name_for_port(connection, login)) {

			found = tds_read_conf_file(connection, tds_dstr_cstr(&connection->server_name));
			/* do it again to really override what found in freetds.conf */
			if (found) {
				parse_server_name_for_port(connection, login);
			} else if (TDS_SUCCEED(tds_lookup_host_set(tds_dstr_cstr(&connection->server_name), &connection->ip_addrs))) {
				if (!tds_dstr_dup(&connection->server_host_name, &connection->server_name)) {
					tds_free_login(connection);
					return NULL;
				}
				found = 1;
			}
		}
	}
	if (!found) {
		/* fallback to interfaces file */
		tdsdump_log(TDS_DBG_INFO1, "Failed in reading conf file.  Trying interface files.\n");
		if (!tds_read_interfaces(tds_dstr_cstr(&login->server_name), connection)) {
			tdsdump_log(TDS_DBG_INFO1, "Failed to find [%s] in configuration files; trying '%s' instead.\n", 
						   tds_dstr_cstr(&login->server_name), tds_dstr_cstr(&connection->server_name));
			if (connection->ip_addrs == NULL)
				tdserror(tds_get_ctx(tds), tds, TDSEINTF, 0);
		}
	}

	/* Override config file settings with environment variables. */
	tds_fix_login(connection);

	/* And finally apply anything from the login structure */
	if (!tds_config_login(connection, login)) {
		tds_free_login(connection);
		return NULL;
	}
	
	if (opened) {
		char tmp[128];

		tdsdump_log(TDS_DBG_INFO1, "Final connection parameters:\n");
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_name", tds_dstr_cstr(&connection->server_name));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_host_name", tds_dstr_cstr(&connection->server_host_name));

		for (addrs = connection->ip_addrs; addrs != NULL; addrs = addrs->ai_next)
			tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "ip_addr", tds_addrinfo2str(addrs, tmp, sizeof(tmp)));

		if (connection->ip_addrs == NULL)
			tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "ip_addr", "");

		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "instance_name", tds_dstr_cstr(&connection->instance_name));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "port", connection->port);
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "major_version", TDS_MAJOR(connection));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "minor_version", TDS_MINOR(connection));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "block_size", connection->block_size);
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "language", tds_dstr_cstr(&connection->language));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_charset", tds_dstr_cstr(&connection->server_charset));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "connect_timeout", connection->connect_timeout);
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "client_host_name", tds_dstr_cstr(&connection->client_host_name));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "client_charset", tds_dstr_cstr(&connection->client_charset));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "use_utf16", connection->use_utf16);
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "app_name", tds_dstr_cstr(&connection->app_name));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "user_name", tds_dstr_cstr(&connection->user_name));
		/* tdsdump_log(TDS_DBG_PASSWD, "\t%20s = %s\n", "password", tds_dstr_cstr(&connection->password)); 
			(no such flag yet) */
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "library", tds_dstr_cstr(&connection->library));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "bulk_copy", (int)connection->bulk_copy);
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "suppress_language", (int)connection->suppress_language);
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "encrypt level", (int)connection->encryption_level);
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "query_timeout", connection->query_timeout);
		/* tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "capabilities", tds_dstr_cstr(&connection->capabilities)); 
			(not null terminated) */
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "database", tds_dstr_cstr(&connection->database));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "dump_file", tds_dstr_cstr(&connection->dump_file));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %x\n", "debug_flags", connection->debug_flags);
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "text_size", connection->text_size);
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "emul_little_endian", connection->emul_little_endian);
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_realm_name", tds_dstr_cstr(&connection->server_realm_name));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_spn", tds_dstr_cstr(&connection->server_spn));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "cafile", tds_dstr_cstr(&connection->cafile));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "crlfile", tds_dstr_cstr(&connection->crlfile));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "check_ssl_hostname", connection->check_ssl_hostname);
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "db_filename", tds_dstr_cstr(&connection->db_filename));
		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "readonly_intent", connection->readonly_intent);

		tdsdump_close();
	}

	/*
	 * If a dump file has been specified, start logging
	 */
	if (!tds_dstr_isempty(&connection->dump_file) && !tdsdump_isopen()) {
		if (connection->debug_flags)
			tds_debug_flags = connection->debug_flags;
		tdsdump_open(tds_dstr_cstr(&connection->dump_file));
	}

	return connection;
}
Example #8
0
/** 
 * Callback function for the DSN Configuration dialog
 * \param hDlg identifies the dialog
 * \param message what happened to the dialog
 * \param wParam varies with message
 * \param lParam pointer to DSNINFO struct
 */
static BOOL CALLBACK
DSNDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	DSNINFO *di;
	char tmp[100];
	const char *pstr;
	int major, minor, i;
	static const char *protocols[] = {
		"TDS 4.2", "TDS 4.6", "TDS 5.0", "TDS 7.0", "TDS 7.1", "TDS 7.2", "TDS 7.3", NULL
	};

	switch (message) {

	case WM_INITDIALOG:
		/* lParam points to the DSNINFO */
		di = (DSNINFO *) lParam;
		SetWindowUserData(hDlg, lParam);

		/* Stuff legal protocol names into IDC_PROTOCOL */
		for (i = 0; protocols[i]; i++) {
			SendDlgItemMessage(hDlg, IDC_PROTOCOL, CB_ADDSTRING, 0, (LPARAM) protocols[i]);
		}

		/* copy info from DSNINFO to the dialog */
		SendDlgItemMessage(hDlg, IDC_DSNNAME, WM_SETTEXT, 0, (LPARAM) tds_dstr_cstr(&di->dsn));
		sprintf(tmp, "TDS %d.%d", TDS_MAJOR(di->login), TDS_MINOR(di->login));
		SendDlgItemMessage(hDlg, IDC_PROTOCOL, CB_SELECTSTRING, -1, (LPARAM) tmp);
		SendDlgItemMessage(hDlg, IDC_ADDRESS, WM_SETTEXT, 0, (LPARAM) tds_dstr_cstr(&di->login->server_name));
		sprintf(tmp, "%u", di->login->port);
		SendDlgItemMessage(hDlg, IDC_PORT, WM_SETTEXT, 0, (LPARAM) tmp);
		SendDlgItemMessage(hDlg, IDC_DATABASE, WM_SETTEXT, 0, (LPARAM) tds_dstr_cstr(&di->login->database));

		return TRUE;

	case WM_COMMAND:
		/* Dialog's user data points to DSNINFO */
		di = (DSNINFO *) GetWindowUserData(hDlg);

		/* The wParam indicates which button was pressed */
		if (LOWORD(wParam) == IDCANCEL) {
			EndDialog(hDlg, FALSE);
			return TRUE;
		} else if (LOWORD(wParam) != IDOK) {
			/* Anything but IDCANCEL or IDOK is handled elsewhere */
			break;
		}
		/* If we get here, then the user hit the [OK] button */

		/* get values from dialog */
		SendDlgItemMessage(hDlg, IDC_DSNNAME, WM_GETTEXT, sizeof tmp, (LPARAM) tmp);
		tds_dstr_copy(&di->dsn, tmp);
		SendDlgItemMessage(hDlg, IDC_PROTOCOL, WM_GETTEXT, sizeof tmp, (LPARAM) tmp);
		minor = 0;
		if (sscanf(tmp, "%*[^0-9]%d.%d", &major, &minor) > 1) {
			if (major == 8 && minor == 0) {
				major = 7;
				minor = 1;
			}
			di->login->tds_version = (major << 8) | minor;
		}
		SendDlgItemMessage(hDlg, IDC_ADDRESS, WM_GETTEXT, sizeof tmp, (LPARAM) tmp);
		tds_dstr_copy(&di->login->server_name, tmp);
		SendDlgItemMessage(hDlg, IDC_PORT, WM_GETTEXT, sizeof tmp, (LPARAM) tmp);
		di->login->port = atoi(tmp);
		SendDlgItemMessage(hDlg, IDC_DATABASE, WM_GETTEXT, sizeof tmp, (LPARAM) tmp);
		tds_dstr_copy(&di->login->database, tmp);

		/* validate */
		SendDlgItemMessage(hDlg, IDC_HINT, WM_SETTEXT, 0, (LPARAM) "VALIDATING... please be patient");
		pstr = validate(di);
		if (pstr != NULL) {
			SendDlgItemMessage(hDlg, IDC_HINT, WM_SETTEXT, 0, (LPARAM) pstr);
			return TRUE;
		}
		SendDlgItemMessage(hDlg, IDC_HINT, WM_SETTEXT, 0, (LPARAM) "");

		/* No problems -- we're done */
		EndDialog(hDlg, TRUE);
		return TRUE;
	}
	return FALSE;
}
Example #9
0
TDSERRNO
tds_open_socket(TDSSOCKET *tds, struct addrinfo *addr, unsigned int port, int timeout, int *p_oserr)
{
	ioctl_nonblocking_t ioctl_nonblocking;
	SOCKLEN_T optlen;
	TDSCONNECTION *conn = tds->conn;
	char ipaddr[128];
	
	int retval, len;
	TDSERRNO tds_error = TDSECONN;

	*p_oserr = 0;

	tds_addrinfo_set_port(addr, port);
	tds_addrinfo2str(addr, ipaddr, sizeof(ipaddr));

	tdsdump_log(TDS_DBG_INFO1, "Connecting to %s port %d (TDS version %d.%d)\n", 
			ipaddr, port,
			TDS_MAJOR(conn), TDS_MINOR(conn));

	conn->s = socket(addr->ai_family, SOCK_STREAM, 0);
	if (TDS_IS_SOCKET_INVALID(conn->s)) {
		char *errstr = sock_strerror(*p_oserr = sock_errno);
		tdsdump_log(TDS_DBG_ERROR, "socket creation error: %s\n", errstr);
		sock_strerror_free(errstr);
		return TDSESOCK;
	}
	tds->state = TDS_IDLE;

#ifdef SO_KEEPALIVE
	len = 1;
	setsockopt(conn->s, SOL_SOCKET, SO_KEEPALIVE, (const void *) &len, sizeof(len));
#endif

#if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
	len = 40;
	setsockopt(conn->s, SOL_TCP, TCP_KEEPIDLE, (const void *) &len, sizeof(len));
	len = 2;
	setsockopt(conn->s, SOL_TCP, TCP_KEEPINTVL, (const void *) &len, sizeof(len));
#endif

#if defined(__APPLE__) && defined(SO_NOSIGPIPE)
	len = 1;
	if (setsockopt(conn->s, SOL_SOCKET, SO_NOSIGPIPE, (const void *) &len, sizeof(len))) {
		*p_oserr = sock_errno;
		tds_connection_close(conn);
		return TDSESOCK;
	}
#endif

	len = 1;
#if defined(USE_NODELAY)
	setsockopt(conn->s, SOL_TCP, TCP_NODELAY, (const void *) &len, sizeof(len));
#elif defined(USE_CORK)
	if (setsockopt(conn->s, SOL_TCP, TCP_CORK, (const void *) &len, sizeof(len)) < 0)
		setsockopt(conn->s, SOL_TCP, TCP_NODELAY, (const void *) &len, sizeof(len));
#else
#error One should be defined
#endif

#ifdef  DOS32X			/* the other connection doesn't work  on WATTCP32 */
	if (connect(conn->s, addr->ai_addr, addr->ai_addrlen) < 0) {
		char *message;

		*p_oserr = sock_errno;
		if (asprintf(&message, "tds_open_socket(): %s:%d", ipaddr, port) >= 0) {
			perror(message);
			free(message);
		}
		tds_connection_close(conn);
		return TDSECONN;
	}
#else
	if (!timeout) {
		/* A timeout of zero means wait forever; 90,000 seconds will feel like forever. */
		timeout = 90000;
	}

	/* enable non-blocking mode */
	ioctl_nonblocking = 1;
	if (IOCTLSOCKET(conn->s, FIONBIO, &ioctl_nonblocking) < 0) {
		*p_oserr = sock_errno;
		tds_connection_close(conn);
		return TDSEUSCT; 	/* close enough: "Unable to set communications timer" */
	}
	retval = connect(conn->s, addr->ai_addr, addr->ai_addrlen);
	if (retval == 0) {
		tdsdump_log(TDS_DBG_INFO2, "connection established\n");
	} else {
		int err = *p_oserr = sock_errno;
		char *errstr = sock_strerror(err);
		tdsdump_log(TDS_DBG_ERROR, "tds_open_socket: connect(2) returned \"%s\"\n", errstr);
		sock_strerror_free(errstr);
#if DEBUGGING_CONNECTING_PROBLEM
		if (err != ECONNREFUSED && err != ENETUNREACH && err != TDSSOCK_EINPROGRESS) {
			tdsdump_dump_buf(TDS_DBG_ERROR, "Contents of sockaddr_in", addr->ai_addr, addr->ai_addrlen);
			tdsdump_log(TDS_DBG_ERROR, 	" sockaddr_in:\t"
							      "%s = %x\n" 
							"\t\t\t%s = %x\n" 
							"\t\t\t%s = %s\n"
							, "sin_family", addr->ai_family
							, "port", port
							, "address", ipaddr
							);
		}
#endif
		if (err != TDSSOCK_EINPROGRESS)
			goto not_available;
		
		*p_oserr = TDSSOCK_ETIMEDOUT;
		if (tds_select(tds, TDSSELWRITE|TDSSELERR, timeout) == 0) {
			tds_error = TDSECONN;
			goto not_available;
		}
	}
#endif	/* not DOS32X */

	/* check socket error */
	optlen = sizeof(len);
	len = 0;
	if (tds_getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (char *) &len, &optlen) != 0) {
		char *errstr = sock_strerror(*p_oserr = sock_errno);
		tdsdump_log(TDS_DBG_ERROR, "getsockopt(2) failed: %s\n", errstr);
		sock_strerror_free(errstr);
		goto not_available;
	}
	if (len != 0) {
		char *errstr = sock_strerror(*p_oserr = len);
		tdsdump_log(TDS_DBG_ERROR, "getsockopt(2) reported: %s\n", errstr);
		sock_strerror_free(errstr);
		goto not_available;
	}

	tdsdump_log(TDS_DBG_ERROR, "tds_open_socket() succeeded\n");
	return TDSEOK;
	
    not_available:
	
	tds_connection_close(conn);
	tdsdump_log(TDS_DBG_ERROR, "tds_open_socket() failed\n");
	return tds_error;
}
Example #10
0
static TDSERRNO
tds_connect_socket(TDSSOCKET *tds, struct addrinfo *addr, unsigned int port, int timeout, int *p_oserr)
{
	SOCKLEN_T optlen;
	TDSCONNECTION *conn = tds->conn;
	char ipaddr[128];

	int retval, len;

	tds_addrinfo_set_port(addr, port);
	tds_addrinfo2str(addr, ipaddr, sizeof(ipaddr));

	if (TDS_IS_SOCKET_INVALID(conn->s))
		return TDSECONN;

	*p_oserr = 0;

	tdsdump_log(TDS_DBG_INFO1, "Connecting to %s port %d (TDS version %d.%d)\n", 
			ipaddr, port,
			TDS_MAJOR(conn), TDS_MINOR(conn));

#ifdef  DOS32X			/* the other connection doesn't work  on WATTCP32 */
	if (connect(conn->s, addr->ai_addr, addr->ai_addrlen) < 0) {
		*p_oserr = sock_errno;
		tdsdump_log(TDS_DBG_ERROR, "tds_open_socket(): %s:%d", ipaddr, port);
		return TDSECONN;
	}
#else
	if (!timeout) {
		/* A timeout of zero means wait forever; 90,000 seconds will feel like forever. */
		timeout = 90000;
	}

	if ((*p_oserr = tds_socket_set_nonblocking(conn->s)) != 0) {
		tds_connection_close(conn);
		return TDSEUSCT; 	/* close enough: "Unable to set communications timer" */
	}
	retval = connect(conn->s, addr->ai_addr, addr->ai_addrlen);
	if (retval == 0) {
		tdsdump_log(TDS_DBG_INFO2, "connection established\n");
	} else {
		int err = *p_oserr = sock_errno;
		char *errstr = sock_strerror(err);
		tdsdump_log(TDS_DBG_ERROR, "tds_open_socket: connect(2) returned \"%s\"\n", errstr);
		sock_strerror_free(errstr);
#if DEBUGGING_CONNECTING_PROBLEM
		if (err != ECONNREFUSED && err != ENETUNREACH && err != TDSSOCK_EINPROGRESS) {
			tdsdump_dump_buf(TDS_DBG_ERROR, "Contents of sockaddr_in", addr->ai_addr, addr->ai_addrlen);
			tdsdump_log(TDS_DBG_ERROR, 	" sockaddr_in:\t"
							      "%s = %x\n" 
							"\t\t\t%s = %x\n" 
							"\t\t\t%s = %s\n"
							, "sin_family", addr->ai_family
							, "port", port
							, "address", ipaddr
							);
		}
#endif
		if (err != TDSSOCK_EINPROGRESS)
			return TDSECONN;
		
		*p_oserr = TDSSOCK_ETIMEDOUT;
		if (tds_select(tds, TDSSELWRITE|TDSSELERR, timeout) == 0)
			return TDSECONN;
	}
#endif	/* not DOS32X */

	/* check socket error */
	optlen = sizeof(len);
	len = 0;
	if (tds_getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (char *) &len, &optlen) != 0) {
		char *errstr = sock_strerror(*p_oserr = sock_errno);
		tdsdump_log(TDS_DBG_ERROR, "getsockopt(2) failed: %s\n", errstr);
		sock_strerror_free(errstr);
		return TDSECONN;
	}
	if (len != 0) {
		char *errstr = sock_strerror(*p_oserr = len);
		tdsdump_log(TDS_DBG_ERROR, "getsockopt(2) reported: %s\n", errstr);
		sock_strerror_free(errstr);
		return TDSECONN;
	}

	return TDSEOK;
}