mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 18:43:02 +01:00
Allow to enforce IPv4 or IPv6 in URL-like connection string.
This commit is contained in:
parent
535a0e5204
commit
13aa5420f2
@ -22,6 +22,19 @@ If a domain name is used in connection string, all addresses (IPv4 and IPv6)
|
|||||||
are tried in the order returned by resolver until a connection is established.
|
are tried in the order returned by resolver until a connection is established.
|
||||||
Only if all attempts fail, the client fails to connect.
|
Only if all attempts fail, the client fails to connect.
|
||||||
|
|
||||||
|
New URL-style connection string format (see README.connection_strings) allows
|
||||||
|
to restrict name lookup to only IPv4 or IPv6 addresses:
|
||||||
|
|
||||||
|
connect 'inet://server.example.org/test';
|
||||||
|
connect 'inet4://server.example.org/test';
|
||||||
|
connect 'inet6://server.example.org/test';
|
||||||
|
|
||||||
|
First example tries all addresses, second only IPv4 ones, third only IPv6
|
||||||
|
ones. This can be used to avoid connection delays on systems where name lookup
|
||||||
|
returns IPv6 addresses for some host names but attempts to connect to them
|
||||||
|
time out rather than failing immediatelly (as reported, this can happen even
|
||||||
|
for name "localhost" on some systems).
|
||||||
|
|
||||||
|
|
||||||
Server
|
Server
|
||||||
------
|
------
|
||||||
|
@ -107,6 +107,13 @@ Examples:
|
|||||||
inet://myserver:fb_db/mydb
|
inet://myserver:fb_db/mydb
|
||||||
inet://localhost:fb_db/mydb
|
inet://localhost:fb_db/mydb
|
||||||
|
|
||||||
|
The "inet" protocol can be replaced by "inet4" or "inet6" to restrict client
|
||||||
|
to IPv4 or IPv6 addresses corresponding to supplied name ("inet" protocol
|
||||||
|
tries all addresses in the order determined by OS):
|
||||||
|
|
||||||
|
inet4://myserver/mydb
|
||||||
|
inet6://myserver/mydb
|
||||||
|
|
||||||
Connect via named pipes:
|
Connect via named pipes:
|
||||||
|
|
||||||
wnet://myserver/C:\db\mydb.fdb
|
wnet://myserver/C:\db\mydb.fdb
|
||||||
|
@ -92,6 +92,8 @@
|
|||||||
|
|
||||||
|
|
||||||
const char* const PROTOCOL_INET = "inet";
|
const char* const PROTOCOL_INET = "inet";
|
||||||
|
const char* const PROTOCOL_INET4 = "inet4";
|
||||||
|
const char* const PROTOCOL_INET6 = "inet6";
|
||||||
const char* const PROTOCOL_WNET = "wnet";
|
const char* const PROTOCOL_WNET = "wnet";
|
||||||
const char* const PROTOCOL_XNET = "xnet";
|
const char* const PROTOCOL_XNET = "xnet";
|
||||||
|
|
||||||
@ -5419,6 +5421,7 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
|
|||||||
**************************************/
|
**************************************/
|
||||||
|
|
||||||
rem_port* port = NULL;
|
rem_port* port = NULL;
|
||||||
|
int inet_af = AF_UNSPEC;
|
||||||
|
|
||||||
cBlock.loadClnt(pb, &parSet);
|
cBlock.loadClnt(pb, &parSet);
|
||||||
authenticateStep0(cBlock);
|
authenticateStep0(cBlock);
|
||||||
@ -5443,7 +5446,12 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ISC_analyze_protocol(PROTOCOL_INET, attach_name, node_name, INET_SEPARATOR) ||
|
if (ISC_analyze_protocol(PROTOCOL_INET4, attach_name, node_name, INET_SEPARATOR))
|
||||||
|
inet_af = AF_INET;
|
||||||
|
else if (ISC_analyze_protocol(PROTOCOL_INET6, attach_name, node_name, INET_SEPARATOR))
|
||||||
|
inet_af = AF_INET6;
|
||||||
|
if (inet_af != AF_UNSPEC ||
|
||||||
|
ISC_analyze_protocol(PROTOCOL_INET, attach_name, node_name, INET_SEPARATOR) ||
|
||||||
ISC_analyze_tcp(attach_name, node_name))
|
ISC_analyze_tcp(attach_name, node_name))
|
||||||
{
|
{
|
||||||
if (node_name.isEmpty())
|
if (node_name.isEmpty())
|
||||||
@ -5455,7 +5463,7 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
|
|||||||
}
|
}
|
||||||
|
|
||||||
port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_UV, pb,
|
port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_UV, pb,
|
||||||
cBlock.getConfig(), ref_db_name);
|
cBlock.getConfig(), ref_db_name, inet_af);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have a local connection string. If it's a file on a network share,
|
// We have a local connection string. If it's a file on a network share,
|
||||||
|
@ -453,7 +453,8 @@ static rem_port* inet_try_connect( PACKET*,
|
|||||||
const TEXT*,
|
const TEXT*,
|
||||||
ClumpletReader&,
|
ClumpletReader&,
|
||||||
RefPtr<Config>*,
|
RefPtr<Config>*,
|
||||||
const PathName*);
|
const PathName*,
|
||||||
|
int);
|
||||||
static bool inet_write(XDR*);
|
static bool inet_write(XDR*);
|
||||||
static rem_port* listener_socket(rem_port* port, USHORT flag, const addrinfo* pai);
|
static rem_port* listener_socket(rem_port* port, USHORT flag, const addrinfo* pai);
|
||||||
|
|
||||||
@ -532,7 +533,8 @@ rem_port* INET_analyze(ClntAuthBlock* cBlock,
|
|||||||
bool uv_flag,
|
bool uv_flag,
|
||||||
ClumpletReader &dpb,
|
ClumpletReader &dpb,
|
||||||
RefPtr<Config>* config,
|
RefPtr<Config>* config,
|
||||||
const PathName* ref_db_name)
|
const PathName* ref_db_name,
|
||||||
|
int af)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -624,7 +626,7 @@ rem_port* INET_analyze(ClntAuthBlock* cBlock,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rem_port* port = inet_try_connect(packet, rdb, file_name, node_name, dpb, config, ref_db_name);
|
rem_port* port = inet_try_connect(packet, rdb, file_name, node_name, dpb, config, ref_db_name, af);
|
||||||
|
|
||||||
P_ACPT* accept = NULL;
|
P_ACPT* accept = NULL;
|
||||||
switch (packet->p_operation)
|
switch (packet->p_operation)
|
||||||
@ -708,7 +710,8 @@ rem_port* INET_connect(const TEXT* name,
|
|||||||
PACKET* packet,
|
PACKET* packet,
|
||||||
USHORT flag,
|
USHORT flag,
|
||||||
ClumpletReader* dpb,
|
ClumpletReader* dpb,
|
||||||
RefPtr<Config>* config)
|
RefPtr<Config>* config,
|
||||||
|
int af)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -800,7 +803,10 @@ rem_port* INET_connect(const TEXT* name,
|
|||||||
|
|
||||||
struct addrinfo gai_hints;
|
struct addrinfo gai_hints;
|
||||||
memset(&gai_hints, 0, sizeof(gai_hints));
|
memset(&gai_hints, 0, sizeof(gai_hints));
|
||||||
gai_hints.ai_family = ((packet || host.hasData() || !ipv6) ? AF_UNSPEC : AF_INET6);
|
if (packet)
|
||||||
|
gai_hints.ai_family = af;
|
||||||
|
else
|
||||||
|
gai_hints.ai_family = ((host.hasData() || !ipv6) ? AF_UNSPEC : AF_INET6);
|
||||||
gai_hints.ai_socktype = SOCK_STREAM;
|
gai_hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
#if !defined(WIN_NT) && !defined(__clang__)
|
#if !defined(WIN_NT) && !defined(__clang__)
|
||||||
@ -811,7 +817,7 @@ rem_port* INET_connect(const TEXT* name,
|
|||||||
|
|
||||||
gai_hints.ai_flags =
|
gai_hints.ai_flags =
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
AI_V4MAPPED |
|
((af == AF_UNSPEC) ? AI_V4MAPPED : 0) |
|
||||||
#endif
|
#endif
|
||||||
AI_ADDRCONFIG | (packet ? 0 : AI_PASSIVE);
|
AI_ADDRCONFIG | (packet ? 0 : AI_PASSIVE);
|
||||||
|
|
||||||
@ -825,7 +831,8 @@ rem_port* INET_connect(const TEXT* name,
|
|||||||
retry_gai = false;
|
retry_gai = false;
|
||||||
n = getaddrinfo(host_str, protocol.c_str(), &gai_hints, &gai_result);
|
n = getaddrinfo(host_str, protocol.c_str(), &gai_hints, &gai_result);
|
||||||
|
|
||||||
if ((n == EAI_FAMILY || (!host_str && n == EAI_NONAME)) && (gai_hints.ai_family == AF_INET6))
|
if ((n == EAI_FAMILY || (!host_str && n == EAI_NONAME)) &&
|
||||||
|
(gai_hints.ai_family == AF_INET6) && (af != AF_INET6))
|
||||||
{
|
{
|
||||||
// May be on a system without IPv6 support, try IPv4
|
// May be on a system without IPv6 support, try IPv4
|
||||||
gai_hints.ai_family = AF_UNSPEC;
|
gai_hints.ai_family = AF_UNSPEC;
|
||||||
@ -2639,7 +2646,8 @@ static rem_port* inet_try_connect(PACKET* packet,
|
|||||||
const TEXT* node_name,
|
const TEXT* node_name,
|
||||||
ClumpletReader& dpb,
|
ClumpletReader& dpb,
|
||||||
RefPtr<Config>* config,
|
RefPtr<Config>* config,
|
||||||
const PathName* ref_db_name)
|
const PathName* ref_db_name,
|
||||||
|
int af)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -2671,7 +2679,7 @@ static rem_port* inet_try_connect(PACKET* packet,
|
|||||||
rem_port* port = NULL;
|
rem_port* port = NULL;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
port = INET_connect(node_name, packet, false, &dpb, config);
|
port = INET_connect(node_name, packet, false, &dpb, config, af);
|
||||||
}
|
}
|
||||||
catch (const Exception&)
|
catch (const Exception&)
|
||||||
{
|
{
|
||||||
|
@ -34,9 +34,10 @@ namespace Firebird
|
|||||||
}
|
}
|
||||||
|
|
||||||
rem_port* INET_analyze(ClntAuthBlock*, const Firebird::PathName&, const TEXT*,
|
rem_port* INET_analyze(ClntAuthBlock*, const Firebird::PathName&, const TEXT*,
|
||||||
bool, Firebird::ClumpletReader&, Firebird::RefPtr<Config>*, const Firebird::PathName*);
|
bool, Firebird::ClumpletReader&, Firebird::RefPtr<Config>*,
|
||||||
|
const Firebird::PathName*, int af = AF_UNSPEC);
|
||||||
rem_port* INET_connect(const TEXT*, struct packet*, USHORT, Firebird::ClumpletReader*,
|
rem_port* INET_connect(const TEXT*, struct packet*, USHORT, Firebird::ClumpletReader*,
|
||||||
Firebird::RefPtr<Config>*);
|
Firebird::RefPtr<Config>*, int af = AF_UNSPEC);
|
||||||
rem_port* INET_reconnect(SOCKET);
|
rem_port* INET_reconnect(SOCKET);
|
||||||
rem_port* INET_server(SOCKET);
|
rem_port* INET_server(SOCKET);
|
||||||
void setStopMainThread(FPTR_INT func);
|
void setStopMainThread(FPTR_INT func);
|
||||||
|
Loading…
Reference in New Issue
Block a user