Index: builds/win32/msvc9/fbembed.vcproj
===================================================================
--- builds/win32/msvc9/fbembed.vcproj	(revision 57120)
+++ builds/win32/msvc9/fbembed.vcproj	(working copy)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="windows-1251"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
-	Version="9,00"
+	Version="9.00"
 	Name="fbembed"
 	ProjectGUID="{C5A60E3D-7815-4127-B856-96277BEC1D11}"
 	TargetFrameworkVersion="131072"
@@ -397,6 +397,10 @@
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath="..\..\..\src\common\inet_nptopn.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\src\remote\interface.cpp"
 				>
 				<FileConfiguration
Index: builds/win32/msvc9/common.vcproj
===================================================================
--- builds/win32/msvc9/common.vcproj	(revision 57120)
+++ builds/win32/msvc9/common.vcproj	(working copy)
@@ -389,6 +389,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\..\src\common\inet_nptopn.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\src\common\classes\UserBlob.cpp"
 				>
 			</File>
@@ -410,6 +414,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\..\src\common\inet_nptopn.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\src\common\classes\array.h"
 				>
 			</File>
Index: builds/win32/msvc9/fb_inet_server.vcproj
===================================================================
--- builds/win32/msvc9/fb_inet_server.vcproj	(revision 57120)
+++ builds/win32/msvc9/fb_inet_server.vcproj	(working copy)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
-	Version="9,00"
+	Version="9.00"
 	Name="fb_inet_server"
 	ProjectGUID="{664D4A04-36E0-48EF-8BCA-D5C331EFAA24}"
 	TargetFrameworkVersion="131072"
@@ -342,6 +342,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\..\src\common\inet_nptopn.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\src\utilities\nbackup.cpp"
 				>
 			</File>
Index: builds/make.new/config/install-sh
===================================================================
--- builds/make.new/config/install-sh	(revision 57120)
+++ builds/make.new/config/install-sh	(working copy)
@@ -1,7 +1,7 @@
 #!/bin/sh
 # install - install a program, script, or datafile
 
-scriptversion=2006-12-25.00
+scriptversion=2010-02-06.18; # UTC
 
 # This originates from X11R5 (mit/util/scripts/install.sh), which was
 # later released in X11R6 (xc/config/util/install.sh) with the
@@ -200,7 +200,11 @@
 fi
 
 if test -z "$dir_arg"; then
-  trap '(exit $?); exit' 1 2 13 15
+  do_exit='(exit $ret); exit $ret'
+  trap "ret=129; $do_exit" 1
+  trap "ret=130; $do_exit" 2
+  trap "ret=141; $do_exit" 13
+  trap "ret=143; $do_exit" 15
 
   # Set umask so as not to create temps with too-generous modes.
   # However, 'strip' requires both read and write access to temps.
@@ -515,5 +519,6 @@
 # eval: (add-hook 'write-file-hooks 'time-stamp)
 # time-stamp-start: "scriptversion="
 # time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-end: "$"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
 # End:
Index: src/jrd/isc_file.cpp
===================================================================
--- src/jrd/isc_file.cpp	(revision 57120)
+++ src/jrd/isc_file.cpp	(working copy)
@@ -82,6 +82,13 @@
 
 #include "../common/config/config.h"
 
+#ifndef WIN_NT
+#include <arpa/inet.h> /* for inet_pton() see ISC_analyze_tcp */
+#endif
+#ifdef WIN_NT
+#include "../common/inet_nptopn.h"
+#endif
+
 const char INET_FLAG = ':';
 
 /* Unix/NFS specific stuff */
@@ -368,13 +375,31 @@
 
 /* Scan file name looking for separator character */
 
+/*
+ * Separator character is : (at the moment) that is also used in
+ * IPv6 addresses, this has been changed to deal with an IPv6 case
+ */
+
 	node_name.erase();
-	const size p = file_name.find(INET_FLAG);
-	if (p == npos || p == 0 || p == file_name.length() - 1)
-		return false;
+	size p = file_name.find(INET_FLAG);
+	size pend;
+	if (file_name[0] == '[' && (pend = file_name.find(']')))
+	{
+		char tmpaddr[16];
+		node_name = file_name.substr(1, pend - 1);
+		if (inet_pton(AF_INET6, node_name.c_str(), tmpaddr) != 1)
+		{
+			node_name.erase();
+			return false;
+		}
+		p = pend + 1;
+	}
+	else {
+		if (p == npos)
+			return false;
+		node_name = file_name.substr(0, p);
+	}
 
-	node_name = file_name.substr(0, p);
-
 #ifdef WIN_NT
 /* For Windows NT, insure that a single character node name does
    not conflict with an existing drive letter. */
Index: src/include/gen/autoconfig_msvc.h
===================================================================
--- src/include/gen/autoconfig_msvc.h	(revision 57120)
+++ src/include/gen/autoconfig_msvc.h	(working copy)
@@ -286,6 +286,9 @@
 /* Windows platforms support threads */
 #define HAVE_MULTI_THREAD 1
 
+/* Ensure FB is listening on inet6 and inet interfaces */
+#define USE_SPECIAL_IPV6_SOCKET
+
 /* CPU types */
 #undef PowerPC
 #undef sparc
@@ -308,6 +311,7 @@
 #define WIN_NT
 #undef SCO_EV
 
+
 #define FB_PREFIX "c:\\Program Files\\Firebird\\"
 
 #define FB_BINDIR ""
Index: src/remote/inet.cpp
===================================================================
--- src/remote/inet.cpp	(revision 57120)
+++ src/remote/inet.cpp	(working copy)
@@ -80,6 +80,9 @@
 
 #ifdef	WIN_NT
 #define FD_SETSIZE 1024
+
+#include <ws2tcpip.h>
+#include "../common/inet_nptopn.h"
 #endif
 
 #ifndef WIN_NT
@@ -451,8 +454,8 @@
 
 #endif
 
-static in_addr get_bind_address();
-static int get_host_address(const char* name, in_addr* const host_addr_arr, const int arr_size);
+static in6_addr * get_bind_address();
+static int get_host_address(const char* name, in6_addr* const host_addr_arr, const int arr_size, const bool includeipv6);
 
 static void copy_p_cnct_repeat_array(	p_cnct::p_cnct_repeat*			pDest,
 										const p_cnct::p_cnct_repeat*	pSource,
@@ -728,6 +731,19 @@
 	return port;
 }
 
+int INET_convertfromv6(struct sockaddr * address) {
+	struct sockaddr_in6 * addr6;
+	struct sockaddr_in * addr4;
+	
+	addr6 = (struct sockaddr_in6 *)address;
+	addr4 = (struct sockaddr_in *)address;
+	
+	memcpy(&addr4->sin_addr, &addr6->sin6_addr.s6_addr[12], 4);
+	address->sa_family = AF_INET;
+	
+	return 0;
+}
+
 rem_port* INET_connect(const TEXT* name,
 					   PACKET* packet,
 					   ISC_STATUS* status_vector,
@@ -767,6 +783,7 @@
 	status_vector[0] = isc_arg_gds;
 	status_vector[1] = 0;
 	status_vector[2] = isc_arg_end;
+	bool tryIPv6 = true;
 
 	Firebird::string host;
 	Firebird::string protocol;
@@ -804,46 +821,14 @@
 
 	// Set up Inter-Net socket address
 
-	struct sockaddr_in address;
+	struct sockaddr_in6 address;
 	memset(&address, 0, sizeof(address));
 
 	// U N I X style sockets
+	// AF_INET6 may change later if host does not support IPv6 sockets
 
-	address.sin_family = AF_INET;
+	address.sin6_family = AF_INET6;
 
-	// define maximum numbers of addresses for a host that we can handle
-	const int MAX_HOST_ADDRESS_NUMBER = 8;
-
-	in_addr host_addr;
-	in_addr host_addr_arr[MAX_HOST_ADDRESS_NUMBER];
-	int hostAddressNumber = 0;
-
-	if (packet)
-	{
-		// client connection
-		hostAddressNumber = get_host_address(host.c_str(), host_addr_arr, MAX_HOST_ADDRESS_NUMBER);
-		if (hostAddressNumber > MAX_HOST_ADDRESS_NUMBER)
-		{
-			hostAddressNumber = MAX_HOST_ADDRESS_NUMBER;
-		}
-
-		if (! hostAddressNumber)
-		{
-			gds__log("INET/INET_connect: gethostbyname (%s) failed, error code = %d",
-					 host.c_str(), H_ERRNO);
-			inet_gen_error(port, Arg::Gds(isc_net_lookup_err) << Arg::Gds(isc_host_unknown));
-
-			disconnect(port);
-			return NULL;
-		}
-		host_addr = host_addr_arr[0];
-	}
-	else
-	{
-		// server connection
-		host_addr = get_bind_address();
-	}
-
 	const struct servent* service = getservbyname(protocol.c_str(), "tcp");
 #ifdef WIN_NT
 	// On Windows NT/9x, getservbyname can only accomodate
@@ -880,7 +865,7 @@
 		if (protocol == FB_SERVICE_NAME)
 		{
 			// apply hardwired translation
-			address.sin_port = htons(FB_SERVICE_PORT);
+			address.sin6_port = htons(FB_SERVICE_PORT);
 		}
 		// modification by FSG 23.MAR.2001
 		else
@@ -889,10 +874,10 @@
 			// The user has supplied something as protocol
 			// let's see whether this is a port number
 			// instead of a service name
-			address.sin_port = htons(atoi(protocol.c_str()));
+			address.sin6_port = htons(atoi(protocol.c_str()));
 		}
 
-		if (address.sin_port == 0)
+		if (address.sin6_port == 0)
 		{
 			// end of modification by FSG
 			// this is the original code
@@ -907,14 +892,28 @@
 		// if we have got a service-struct, get port number from there
 		// (in case of hardwired gds_db to 3050 translation, address.sin_port was
 		// already set above
-		address.sin_port = service->s_port;
+		address.sin6_port = service->s_port;
 	}							// else (service found)
 
 	// end of modifications by luz
 
 	// Allocate a port block and initialize a socket for communications
 
-	port->port_handle = socket(AF_INET, SOCK_STREAM, 0);
+	port->port_handle = INVALID_SOCKET;
+	// if this call is for a server and the SRVR_inet6 flag
+	// or this is NOT a server call
+	if (((flag & SRVR_inet6) && (flag & SRVR_server || flag & SRVR_multi_client)) ||
+		!(flag & SRVR_server || flag & SRVR_multi_client))
+	{
+		gds__log("INET/INET_connect: creating a v6 socket");
+		port->port_handle = socket(AF_INET6, SOCK_STREAM, 0);
+	}
+	// IPv6 may have failed because of underlying operating system support
+	if (port->port_handle == INVALID_SOCKET)
+	{
+		port->port_flags |= PORT_v4;
+		port->port_handle = socket(AF_INET, SOCK_STREAM, 0);
+	}
 
 	if (port->port_handle == INVALID_SOCKET)
 	{
@@ -923,9 +922,50 @@
 		return NULL;
 	}
 
+	// Moved from earlier so we know what kind of addresses are acceptable
+	// IPv6 and IPv4 or just IPv4
+	// define maximum numbers of addresses for a host that we can handle
+	const int MAX_HOST_ADDRESS_NUMBER = 8;
+
+	in6_addr host_addr;
+	in6_addr host_addr_arr[MAX_HOST_ADDRESS_NUMBER];
+	int hostAddressNumber = 0;
+	
+	if (packet)
+	{
+		// client connection
+		hostAddressNumber = get_host_address(host.c_str(), host_addr_arr, MAX_HOST_ADDRESS_NUMBER,
+			port->port_flags & PORT_v4 ? 0 : 1);
+		if (hostAddressNumber > MAX_HOST_ADDRESS_NUMBER)
+		{
+			hostAddressNumber = MAX_HOST_ADDRESS_NUMBER;
+		}
+		if (hostAddressNumber == 1 && port->port_flags & PORT_v4) {
+			const UCHAR loopbkaddr6[] = { 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 1 };
+			const UCHAR loopbkaddr4[] = { 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0xff, 0xff, 127, 0, 0, 1 };
+
+			if (memcmp((void *)host_addr_arr, loopbkaddr6, 16) == 0) {
+				memcpy((void *)host_addr_arr, loopbkaddr4, 16);
+			}
+		}
+
+		if (! hostAddressNumber)
+		{
+			gds__log("INET/INET_connect: gethostbyname (%s) failed, error code = %d",
+					 host.c_str(), H_ERRNO);
+			inet_gen_error(port, Arg::Gds(isc_net_lookup_err) << Arg::Gds(isc_host_unknown));
+		}
+		memcpy(&host_addr, &host_addr_arr[0], sizeof(in6_addr));
+	}
+	else
+	{
+		// server connection
+		memcpy(&host_addr, get_bind_address(), sizeof(in6_addr));
+	}
+
 	// If we're a host, just make the connection
 
-    int n;
+	int n;
 
 	if (packet)
 	{
@@ -947,11 +987,17 @@
 		int inetErrNo = 0;
 		for (int i = 0; i < hostAddressNumber; i++)
 		{
-			address.sin_addr = host_addr_arr[i];
+			address.sin6_addr = host_addr_arr[i];
 
 			// If host has two addresses and the first one failed,
 			// but the second one succeeded - no need to worry
 
+			if (port->port_flags & PORT_v4)
+			{
+				INET_convertfromv6((struct sockaddr*) &address);
+				((struct sockaddr*) &address)->sa_family = AF_INET;
+			}
+
 			n = connect(port->port_handle, (struct sockaddr*) &address, sizeof(address));
 			inetErrNo = INET_ERRNO;
 
@@ -965,7 +1011,7 @@
 
 	// We're a server, so wait for a host to show up
 
-	memcpy(&address.sin_addr, &host_addr, sizeof(address.sin_addr));
+	memcpy(&address.sin6_addr, &host_addr, sizeof(address.sin6_addr));
 
 	if (flag & SRVR_multi_client)
 	{
@@ -990,6 +1036,24 @@
 			return NULL;
 		}
 #endif
+#ifdef USE_SPECIAL_IPV6_SOCKET
+		if (!(port->port_flags & PORT_v4)) {
+			// We are a server and want to only bind to the IPv6 addresses
+			int ipv6only = 1;
+			setsockopt(port->port_handle, IPPROTO_IPV6, IPV6_V6ONLY, (SCHAR*)&ipv6only, (socklen_t)sizeof(int));
+		}
+#else
+		if (!(port->port_flags & PORT_v4)) {
+			// We are a server and want to bind to IPv6 and IPv4 addresses
+			int ipv6only = 0;
+			setsockopt(port->port_handle, IPPROTO_IPV6, IPV6_V6ONLY, (SCHAR*)&ipv6only, (socklen_t)sizeof(int));
+		}
+#endif
+		
+		if (port->port_flags & PORT_v4) {
+			INET_convertfromv6((struct sockaddr *)&address);
+			((struct sockaddr *)&address)->sa_family = AF_INET;
+		}
 
 		// Get any values for SO_LINGER so that they can be reset during
 		// disconnect.  SO_LINGER should be set by default on the socket
@@ -1076,6 +1140,9 @@
 			}
 			return NULL;
 		}
+		if (((struct sockaddr *)&address)->sa_family == AF_INET) {
+			port->port_flags |= PORT_v4;
+		}
 #ifdef WIN_NT
 		if (flag & SRVR_debug)
 #else
@@ -1314,24 +1381,28 @@
 	temp.printf("%s.%ld.%ld", name.c_str(), eff_gid, eff_uid);
 	port->port_user_name = REMOTE_make_string(temp.c_str());
 
-	port->port_protocol_str = REMOTE_make_string("TCPv4");
-
-	struct sockaddr_in address;
+	struct sockaddr_in6 address;
 	socklen_t l = sizeof(address);
 
 	memset(&address, 0, sizeof(address));
 	int status = getpeername(port->port_handle, (struct sockaddr *) &address, &l);
 	if (status == 0)
 	{
-		Firebird::string addr_str;
-		const UCHAR* ip = (UCHAR*) &address.sin_addr;
-		addr_str.printf(
-			"%d.%d.%d.%d",
-			static_cast<int>(ip[0]),
-			static_cast<int>(ip[1]),
-			static_cast<int>(ip[2]),
-			static_cast<int>(ip[3]) );
-		port->port_address_str = REMOTE_make_string(addr_str.c_str());
+		if (((struct sockaddr *)&address)->sa_family == AF_INET) {
+			char ipv4pres[INET_ADDRSTRLEN];
+			port->port_protocol_str = REMOTE_make_string("TCPv4");
+			inet_ntop(AF_INET,
+				&((struct sockaddr_in *)&address)->sin_addr.s_addr,
+				ipv4pres, INET_ADDRSTRLEN);
+			port->port_address_str = REMOTE_make_string(ipv4pres);
+			port->port_flags |= PORT_v4;
+		} else if (((struct sockaddr *)&address)->sa_family == AF_INET6) {
+			char ipv6pres[INET6_ADDRSTRLEN];
+			port->port_protocol_str = REMOTE_make_string("TCPv6");
+			inet_ntop(AF_INET6, &address.sin6_addr, ipv6pres,
+				INET6_ADDRSTRLEN);
+			port->port_address_str = REMOTE_make_string(ipv6pres);
+		}
 	}
 
 	return true;
@@ -1444,7 +1515,7 @@
  *	done a successfull connect request ("packet" contains the response).
  *
  **************************************/
-	struct sockaddr_in address;
+	struct sockaddr_in6 address;
 	socklen_t l = sizeof(address);
 
 	// If this is a server, we're got an auxiliary connection.  Accept it
@@ -1486,6 +1557,10 @@
 		const SOCKET n = accept(port->port_channel, (struct sockaddr*) &address, &l);
 		inetErrNo = INET_ERRNO;
 
+		if (((struct sockaddr *)&address)->sa_family == AF_INET) {
+			port->port_flags |= PORT_v4;
+		}
+
 		if (n == INVALID_SOCKET)
 		{
 			inet_error(port, "accept", isc_net_event_connect_err, inetErrNo);
@@ -1503,13 +1578,21 @@
 	port->port_async = new_port;
 	new_port->port_dummy_packet_interval = port->port_dummy_packet_interval;
 	new_port->port_dummy_timeout = new_port->port_dummy_packet_interval;
-	new_port->port_flags = port->port_flags & PORT_no_oob;
+	new_port->port_flags = port->port_flags & (PORT_no_oob | PORT_v4);
 	new_port->port_flags |= PORT_async;
 	P_RESP* response = &packet->p_resp;
 
 	// Set up new socket
 
-	SOCKET n = socket(AF_INET, SOCK_STREAM, 0);
+	SOCKET n;
+	if (new_port->port_flags & PORT_v4)
+	{
+		n = socket(AF_INET, SOCK_STREAM, 0);
+	}
+	else {
+		n = socket(AF_INET6, SOCK_STREAM, 0);
+	}
+
 	if (n == INVALID_SOCKET)
 	{
 		inet_error(port, "socket", isc_net_event_connect_err, INET_ERRNO);
@@ -1533,9 +1616,18 @@
 		SOCLOSE(n);
 		return NULL;
 	}
-	address.sin_family = AF_INET;
-	address.sin_port = ((struct sockaddr_in *)(response->p_resp_data.cstr_address))->sin_port;
+//	address.sin_family = AF_INET;
+//	address.sin_port = ((struct sockaddr_in *)(response->p_resp_data.cstr_address))->sin_port;
 
+	// Conversion from an IPv6 struct is not required because this is already an IPv4 (AF_INET / sockaddr_in) struct
+	// Also, sin6_port and sin_port occupy the same place in the structure... now that was lucky ;-)
+	address.sin6_port = ((struct sockaddr_in6 *)(response->p_resp_data.cstr_address))->sin6_port;
+
+	if (address.sin6_family == AF_INET6)
+	{
+		INET_convertfromv6((struct sockaddr *) &address);
+	}
+
 	int optval = 1;
 	setsockopt(n, SOL_SOCKET, SO_KEEPALIVE, (SCHAR*) &optval, sizeof(optval));
 
@@ -1567,16 +1659,26 @@
  *	connection; the server calls aux_request to set up the connection.
  *
  **************************************/
-	struct sockaddr_in address;
+	struct sockaddr_in6 address;
 
 	// Set up new socket
 
-	address.sin_family = AF_INET;
-	in_addr bind_addr = get_bind_address();
-	memcpy(&address.sin_addr, &bind_addr, sizeof(address.sin_addr));
-	address.sin_port = htons(Config::getRemoteAuxPort());
+	address.sin6_family = AF_INET6;
+	in6_addr bind_addr;
+	memcpy(&bind_addr, get_bind_address(), sizeof(in6_addr));
+	memcpy(&address.sin6_addr, &bind_addr, sizeof(address.sin6_addr));
+	address.sin6_port = htons(Config::getRemoteAuxPort());
 
-	SOCKET n = socket(AF_INET, SOCK_STREAM, 0);
+	SOCKET n;
+	if (port->port_flags & PORT_v4)
+	{
+		INET_convertfromv6((struct sockaddr *)&address);
+		n = socket(AF_INET, SOCK_STREAM, 0);
+	}
+	else {
+		n = socket(AF_INET6, SOCK_STREAM, 0);
+	}
+
 	if (n == INVALID_SOCKET)
 	{
 		inet_error(port, "socket", isc_net_event_listen_err, INET_ERRNO);
@@ -1617,24 +1719,24 @@
 		return NULL;
 	}
 
-    rem_port* const new_port = alloc_port(port->port_parent, PORT_async);
+	rem_port* const new_port = alloc_port(port->port_parent, PORT_async);
 	port->port_async = new_port;
 	new_port->port_dummy_packet_interval = port->port_dummy_packet_interval;
 	new_port->port_dummy_timeout = new_port->port_dummy_packet_interval;
 
 	new_port->port_server_flags = port->port_server_flags;
 	new_port->port_channel = (int) n;
-	new_port->port_flags |= port->port_flags & PORT_no_oob;
+	new_port->port_flags |= port->port_flags & (PORT_no_oob | PORT_v4);
 
 	P_RESP* response = &packet->p_resp;
 
-	struct sockaddr_in port_address;
+	struct sockaddr_in6 port_address;
 	if (getsockname(port->port_handle, (struct sockaddr *) &port_address, &length) < 0)
 	{
 		inet_error(port, "getsockname", isc_net_event_listen_err, INET_ERRNO);
 		return NULL;
 	}
-	memcpy(&address.sin_addr, &port_address.sin_addr, sizeof(address.sin_addr));
+	memcpy(&address.sin6_addr, &port_address.sin6_addr, sizeof(address.sin6_addr));
 
 	response->p_resp_data.cstr_length = sizeof(address);
 	memcpy(response->p_resp_data.cstr_address, &address, sizeof(address));
@@ -1655,15 +1757,29 @@
  *	Check the host on the other end of the socket to see if it's localhost
  *
  **************************************/
-	struct sockaddr_in address;
+	struct sockaddr_in6 address;
+	/* this is the IPv6 loopback address */
+	const u_int8_t loopbkaddr6[] = { 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 1 };
+	const u_int8_t loopbkaddr4[] = { 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0xff, 0xff, 127, 0, 0, 1 };
 
 	socklen_t length = sizeof(address);
 
 	if (getpeername(port->port_handle, (struct sockaddr*) &address, &length) == -1)
 		return false;
 
+	// is this an IPv4 sockaddr?
+	if (address.sin6_family == AF_INET) {
+		return (ntohl(((struct sockaddr_in *)&address)->sin_addr.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET;
+	} else
+	// it's IPv6... or 4/6
+ 	// If source address is in the loopback net - trust it
+	if ( memcmp(loopbkaddr6, &address.sin6_addr, 16) == 0 || memcmp(loopbkaddr4, &address.sin6_addr, 13) == 0) {
+		return true;
+	}
+	return false;
+
 	// If source address is in the loopback net - trust it
-	return (ntohl(address.sin_addr.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET;
+	//return (ntohl(address.sin_addr.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET;
 }
 #endif // WIN_NT
 
@@ -1930,7 +2046,7 @@
 
 namespace
 {
-	in_addr config_address;
+	in6_addr config_address;
 
 	class GetAddress
 	{
@@ -1940,12 +2056,14 @@
 			const char* config_option = Config::getRemoteBindAddress();
 			if (config_option)
 			{
-				int n = get_host_address(config_option, &config_address, 1);
+				int n = get_host_address(config_option, &config_address, 1, 1);
 				if (n != 1)
 				{
 					// In case when config option is given with error,
 					// bind to loopback interface only
-					config_address.s_addr = htonl(INADDR_LOOPBACK);
+					//config_address.s_addr = htonl(INADDR_LOOPBACK);
+					memset(&config_address, 0, sizeof(in6_addr));
+					((char *)&config_address)[15] = 1;
 					// log warning
 					if (n == 0)
 					{
@@ -1961,7 +2079,7 @@
 			}
 			else	// use default to listen all
 			{
-				config_address.s_addr = INADDR_ANY;
+				memset(&config_address, 0, sizeof(in6_addr));
 			}
 		}
 
@@ -1969,7 +2087,7 @@
 	};
 }
 
-static in_addr get_bind_address()
+static in6_addr * get_bind_address()
 {
 /**************************************
  *
@@ -1985,7 +2103,7 @@
 
 	instance.init();
 
-	return config_address;
+	return &config_address;
 }
 
 
@@ -2000,8 +2118,9 @@
 
 
 static int get_host_address(const char* name,
-							in_addr* const host_addr_arr,
-							const int arr_size)
+							in6_addr* const host_addr_arr,
+							const int arr_size,
+							const bool includeipv6)
 {
 /**************************************
  *
@@ -2010,16 +2129,23 @@
  **************************************
  *
  * Functional description
- *  Fills array with addresses up to arr_size (must be at least 1).
+ *	Fills array with addresses up to arr_size (must be at least 1).
  *	Returns the required number of elements in array to be able to store
  *	all host addresses (may be less, equal or greater than arr_size).
  *
  **************************************/
-	if (inet_aton(name, &host_addr_arr[0]))
+	if (inet_pton(AF_INET, name, (((char *)&host_addr_arr[0]) + 12)))
 	{
+		memset(&host_addr_arr[0], 0, sizeof(in6_addr) - (4 + 2));
+		memset((((char *)&host_addr_arr[0]) + 10), 0xFF, 2);
 		return 1;
 	}
 
+	if (includeipv6 && inet_pton(AF_INET6, name, &host_addr_arr[0]))
+	{
+		return 1;
+	}
+
 	const hostent* host = gethostbyname(name);
 
 	// On Windows NT/9x, gethostbyname can only accomodate
@@ -2030,33 +2156,58 @@
 	// retry the operation a few times.
 	// NOTE: This still does not guarantee success, but helps.
 
-	if (!host)
+	struct addrinfo * result;
+	int res;
+
+	res = getaddrinfo(name, NULL, NULL, &result);
+
+	if (res)
 	{
 		for (int retry = 0; H_ERRNO == INET_RETRY_ERRNO && retry < INET_RETRY_CALL; retry++)
 		{
-			if ( (host = gethostbyname(name)) )
+			if (getaddrinfo(name, NULL, NULL, &result) == 0)
 				break;
 		}
 	}
 
-	// We can't work with other types for now. Maybe AF_NETBIOS for MS, too?
-	if (host && host->h_addrtype == AF_INET)
+	struct addrinfo *listelement;
+	listelement = result;
+	int i = 0;
+
+	// here we prefer IPv6 addresses, they will fail in the connect stage of an IPv4 only server
+	if (includeipv6)
 	{
-		const in_addr* const* list = reinterpret_cast<in_addr**>(host->h_addr_list);
-		int i = 0;
-		while (list[i] != NULL)
-		{
-			if (i < arr_size)
+		while (listelement != NULL)
+ 		{
+			if (listelement->ai_family == AF_INET6 && i < arr_size)
 			{
-				host_addr_arr[i] = *list[i];
+				memcpy(&host_addr_arr[i],
+					&((struct sockaddr_in6 *)&listelement->ai_addr)->sin6_addr,
+					sizeof(in6_addr));
+				i ++;
 			}
-			++i;
+			listelement = listelement->ai_next;
 		}
-		return i;
 	}
 
-	// give up
-	return 0;
+	// put the IPv4 addresses after the IPv6 ones
+	listelement = result;
+	while (listelement != NULL) {
+		if (listelement->ai_family == AF_INET && i < arr_size) {
+			// little hack to for IPv4 only addresses that will work with IPv4 and IPv6 hosts.
+			memset(&host_addr_arr[i], 0, sizeof(in6_addr) - (4 + 2));
+			memset((((char *)&host_addr_arr[i]) + 10), 0xFF, 2);
+			memcpy((((char *)&host_addr_arr[i]) + 12), &((struct sockaddr_in *)&listelement->ai_addr)->sin_addr, sizeof(in_addr));
+			i++;
+		}
+		listelement = listelement->ai_next;
+	}
+
+	freeaddrinfo(result);
+
+	return i;
+
+	// We can't work with other types for now. Maybe AF_NETBIOS for MS, too?
 }
 
 //____________________________________________________________
@@ -2208,7 +2359,7 @@
  *	Accept a new connection request.
  *
  **************************************/
-	struct sockaddr_in address;
+	struct sockaddr_in6 address;
 
 	rem_port* const port = alloc_port(main_port);
 	socklen_t l = sizeof(address);
Index: src/remote/os/win32/srvr_w32.cpp
===================================================================
--- src/remote/os/win32/srvr_w32.cpp	(revision 57120)
+++ src/remote/os/win32/srvr_w32.cpp	(working copy)
@@ -367,7 +367,7 @@
 	while (!server_shutdown)
 	{
 		fb_utils::init_status(status_vector);
-		rem_port* port = INET_connect(protocol_inet, NULL, status_vector, server_flag, 0);
+		rem_port* port = INET_connect(protocol_inet, NULL, status_vector, server_flag & ~SRVR_inet6 , 0);
 
 		if (!port)
 		{
@@ -390,7 +390,47 @@
 	return 0;
 }
 
+static THREAD_ENTRY_DECLARE inet6_connect_wait_thread(THREAD_ENTRY_PARAM tep)
+{
+/**************************************
+ *
+ *      i n e t 6 _ c o n n e c t _ w a i t _ t h r e a d
+ *
+ **************************************
+ *
+ * Functional description
+ *
+ **************************************/
+	ThreadCounter counter;
 
+	ISC_STATUS_ARRAY status_vector;
+	while (!server_shutdown)
+	{
+		fb_utils::init_status(status_vector);
+		rem_port* port = INET_connect(protocol_inet, NULL, status_vector, server_flag, 0);
+
+		if (!port)
+		{
+			if (status_vector[1]) {
+				gds__log_status(0, status_vector);
+			}
+			break;
+		}
+		if (server_flag & SRVR_multi_client)
+		{
+			SRVR_multi_thread(port, server_flag);
+			break;
+		}
+		if (gds__thread_start(process_connection_thread, port, THREAD_medium, 0, 0))
+		{
+			gds__log("INET6: can't start worker thread, connection terminated");
+			port->disconnect(NULL, NULL);
+		}
+	}
+	return 0;
+}
+
+
 static THREAD_ENTRY_DECLARE wnet_connect_wait_thread(THREAD_ENTRY_PARAM)
 {
 /**************************************
@@ -488,7 +528,7 @@
 }
 
 
-static THREAD_ENTRY_DECLARE start_connections_thread(THREAD_ENTRY_PARAM)
+static THREAD_ENTRY_DECLARE start_connections_thread(THREAD_ENTRY_PARAM tep)
 {
 /**************************************
  *
@@ -501,6 +541,11 @@
  **************************************/
 	ThreadCounter counter;
 
+#ifdef USE_SPECIAL_IPV6_SOCKET
+	if (server_flag & SRVR_inet6) {
+		gds__thread_start(inet6_connect_wait_thread, 0, THREAD_medium, 0, 0);
+	}
+#endif
 	if (server_flag & SRVR_inet) {
 		gds__thread_start(inet_connect_wait_thread, 0, THREAD_medium, 0, 0);
 	}
@@ -693,6 +738,10 @@
 					*pserver_flag |= SRVR_xnet;
 					break;
 
+				case '6':
+					*pserver_flag |= SRVR_inet6;
+					break;
+
 				case 'Z':
 					// CVC: printf doesn't work because we don't have a console attached.
 					//printf("Firebird remote server version %s\n",  FB_VERSION);
@@ -710,11 +759,12 @@
 		}
 	}
 
-	if ((*pserver_flag & (SRVR_inet | SRVR_wnet | SRVR_xnet)) == 0)
+	if ((*pserver_flag & (SRVR_inet | SRVR_wnet | SRVR_xnet | SRVR_inet6)) == 0)
 	{
 		*pserver_flag |= SRVR_wnet;
 		*pserver_flag |= SRVR_inet;
 		*pserver_flag |= SRVR_xnet;
+		*pserver_flag |= SRVR_inet6;
 	}
 
 	return connection_handle;
Index: src/remote/remote.h
===================================================================
--- src/remote/remote.h	(revision 57120)
+++ src/remote/remote.h	(working copy)
@@ -589,6 +589,7 @@
 const USHORT PORT_server		= 0x0200;	// Server (not client) port
 const USHORT PORT_detached		= 0x0400;	// op_detach, op_drop_database or op_service_detach was processed
 const USHORT PORT_rdb_shutdown	= 0x0800;	// Database is shut down
+const USHORT PORT_v4		= 0x1000;	// This is an IPv4 only port
 
 // Port itself
 
Index: src/remote/remote_def.h
===================================================================
--- src/remote/remote_def.h	(revision 57120)
+++ src/remote/remote_def.h	(working copy)
@@ -85,5 +85,6 @@
 const USHORT SRVR_high_priority		= 128;	// fork off server at high priority
 const USHORT SRVR_thread_per_port	= 256;	// bind thread to a port
 const USHORT SRVR_no_icon			= 512;	// tell the server not to show the icon
+const USHORT SRVR_inet6			= 1024; // inet6 protocol server
 
 #endif /* REMOTE_REMOTE_DEF_H */
Index: src/remote/inet_server.cpp
===================================================================
--- src/remote/inet_server.cpp	(revision 57120)
+++ src/remote/inet_server.cpp	(working copy)
@@ -370,7 +370,7 @@
 		}
 		{ // scope block
 			ISC_STATUS_ARRAY status_vector;
-			port = INET_connect(protocol, 0, status_vector, INET_SERVER_flag, 0);
+			port = INET_connect(protocol, 0, status_vector, INET_SERVER_flag | SRVR_inet6, 0);
 			if (!port)
 			{
 				gds__print_status(status_vector);
