8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 21:23:04 +01:00

1. Fixed CORE-2087: server binds to all interfaces in case of error in firebird.conf.

2. Fixed CORE-2093: Superserver startup fails on solaris / 64 bit.

3. Improvement CORE-2094: Make it possible to use hostname when specifying interface to listen on in firebird.conf.

Almost impossible to separate: came in one week and required modifications in same part of code.
This commit is contained in:
alexpeshkoff 2008-09-22 14:46:13 +00:00
parent 2a57dedf0e
commit 14f21f568e
2 changed files with 97 additions and 57 deletions

View File

@ -528,6 +528,7 @@ if test "$EDITLINE_FLG" = "Y"; then
fi fi
if test "$RT_LIB_CHECK" = "true"; then if test "$RT_LIB_CHECK" = "true"; then
AC_CHECK_LIB(rt, main) AC_CHECK_LIB(rt, main)
AC_CHECK_LIB(resolv, inet_aton)
fi fi
dnl check for INFINITY in math.h dnl check for INFINITY in math.h

View File

@ -268,9 +268,9 @@ static int fork(SOCKET, USHORT);
#endif #endif
static in_addr get_bind_address(); static in_addr get_bind_address();
static in_addr get_host_address(const Firebird::string& name, static int get_host_address(const char* name,
in_addr* const host_addr_arr, in_addr* const host_addr_arr,
const int arr_size); const int arr_size);
static void copy_p_cnct_repeat_array( p_cnct::p_cnct_repeat* pDest, static void copy_p_cnct_repeat_array( p_cnct::p_cnct_repeat* pDest,
const p_cnct::p_cnct_repeat* pSource, const p_cnct::p_cnct_repeat* pSource,
@ -647,12 +647,17 @@ rem_port* INET_connect(const TEXT* name,
in_addr host_addr; in_addr host_addr;
in_addr host_addr_arr[MAX_HOST_ADDRESS_NUMBER]; in_addr host_addr_arr[MAX_HOST_ADDRESS_NUMBER];
int hostAddressNumber = 0;
if (packet) { if (packet) {
// client connection // client connection
host_addr = get_host_address(host, host_addr_arr, MAX_HOST_ADDRESS_NUMBER); 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 (host_addr.s_addr == INADDR_NONE) if (! hostAddressNumber)
{ {
gds__log("INET/INET_connect: gethostbyname (%s) failed, error code = %d", gds__log("INET/INET_connect: gethostbyname (%s) failed, error code = %d",
host.c_str(), H_ERRNO); host.c_str(), H_ERRNO);
@ -664,6 +669,7 @@ rem_port* INET_connect(const TEXT* name,
disconnect(port); disconnect(port);
return NULL; return NULL;
} }
host_addr = host_addr_arr[0];
} }
else { else {
// server connection // server connection
@ -758,11 +764,9 @@ rem_port* INET_connect(const TEXT* name,
} }
int inetErrNo = 0; int inetErrNo = 0;
for (int i = 0; i < MAX_HOST_ADDRESS_NUMBER; i++) for (int i = 0; i < hostAddressNumber; i++)
{ {
address.sin_addr = host_addr_arr[i]; address.sin_addr = host_addr_arr[i];
if (address.sin_addr.s_addr == 0L)
break; // all addresses tried and failed - get out and print the last error
// If host has two addresses and the first one failed, // If host has two addresses and the first one failed,
// but the second one succeeded - no need to worry // but the second one succeeded - no need to worry
@ -1808,6 +1812,47 @@ static int fork( SOCKET old_handle, USHORT flag)
} }
#endif #endif
namespace
{
in_addr config_address;
class GetAddress
{
public:
static void init()
{
const char* config_option = Config::getRemoteBindAddress();
if (config_option)
{
int n = get_host_address(config_option, &config_address, 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);
// log warning
if (n == 0)
{
gds__log("Wrong RemoteBindAddress '%s' in firebird.conf - "
"binding to loopback interface", config_option);
}
else
{
gds__log("Host '%s' resolves to multiple inrefaces - "
"binding to loopback interface", config_option);
}
}
}
else // use default to listen all
{
config_address.s_addr = INADDR_ANY;
}
}
static void cleanup() { }
};
}
static in_addr get_bind_address() static in_addr get_bind_address()
{ {
/************************************** /**************************************
@ -1820,20 +1865,16 @@ static in_addr get_bind_address()
* Return local address to bind sockets to. * Return local address to bind sockets to.
* *
**************************************/ **************************************/
in_addr config_address; static Firebird::InitMutex<GetAddress> instance;
instance.init();
const char* config_option = Config::getRemoteBindAddress();
config_address.s_addr =
(config_option) ? inet_addr(config_option) : INADDR_NONE;
if (config_address.s_addr == INADDR_NONE) {
config_address.s_addr = INADDR_ANY;
}
return config_address; return config_address;
} }
static in_addr get_host_address(const Firebird::string& name, static int get_host_address(const char* name,
in_addr* const host_addr_arr, in_addr* const host_addr_arr,
const int arr_size) const int arr_size)
{ {
/************************************** /**************************************
* *
@ -1842,53 +1883,51 @@ static in_addr get_host_address(const Firebird::string& name,
************************************** **************************************
* *
* Functional description * Functional description
* Fills array with addresses up to arr_size (must be at least 2) * Fills array with addresses up to arr_size (must be at least 1).
* Return first address from the list. * Returns require 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]))
host_addr_arr[0].s_addr = inet_addr(name.c_str());
host_addr_arr[1].s_addr = 0L;
if (host_addr_arr[0].s_addr == INADDR_NONE)
{ {
const hostent* host = gethostbyname(name.c_str()); return 1;
}
/* On Windows NT/9x, gethostbyname can only accomodate const hostent* host = gethostbyname(name);
* 1 call at a time. In this case it returns the error
* WSAEINPROGRESS. On UNIX systems, this call may not succeed
* because of a temporary error. In this case, it returns
* h_error set to TRY_AGAIN. When these errors occur,
* retry the operation a few times.
* NOTE: This still does not guarantee success, but helps.
*/
if (!host) {
if (H_ERRNO == INET_RETRY_ERRNO) {
for (int retry = 0; retry < INET_RETRY_CALL; retry++) {
if ( (host = gethostbyname(name.c_str())) )
break;
}
}
}
// We can't work with other types for now. Maybe AF_NETBIOS for MS, too? /* On Windows NT/9x, gethostbyname can only accomodate
if (host && host->h_addrtype == AF_INET) * 1 call at a time. In this case it returns the error
{ * WSAEINPROGRESS. On UNIX systems, this call may not succeed
const in_addr* const* list = reinterpret_cast<in_addr**>(host->h_addr_list); * because of a temporary error. In this case, it returns
for (int i = 0; i < arr_size; ++i) * h_error set to TRY_AGAIN. When these errors occur,
{ * retry the operation a few times.
if (list[i] == NULL) * NOTE: This still does not guarantee success, but helps.
{ */
// Mark the end of the useful entries in host_addr_arr. if ((!host) && (H_ERRNO == INET_RETRY_ERRNO)) {
host_addr_arr[i].s_addr = 0L; for (int retry = 0; retry < INET_RETRY_CALL; retry++) {
break; if ( (host = gethostbyname(name)) )
} break;
host_addr_arr[i] = *list[i];
}
} }
} }
return host_addr_arr[0]; // We can't work with other types for now. Maybe AF_NETBIOS for MS, too?
if (host && host->h_addrtype == AF_INET)
{
const in_addr* const* list = reinterpret_cast<in_addr**>(host->h_addr_list);
int i = 0;
while (list[i] != NULL)
{
if (i < arr_size)
{
host_addr_arr[i] = *list[i];
}
++i;
}
return i;
}
// give up
return 0;
} }
//____________________________________________________________ //____________________________________________________________