mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:03:03 +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.
|
||||
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
|
||||
------
|
||||
|
@ -107,6 +107,13 @@ Examples:
|
||||
inet://myserver: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:
|
||||
|
||||
wnet://myserver/C:\db\mydb.fdb
|
||||
|
@ -92,6 +92,8 @@
|
||||
|
||||
|
||||
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_XNET = "xnet";
|
||||
|
||||
@ -5419,6 +5421,7 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
|
||||
**************************************/
|
||||
|
||||
rem_port* port = NULL;
|
||||
int inet_af = AF_UNSPEC;
|
||||
|
||||
cBlock.loadClnt(pb, &parSet);
|
||||
authenticateStep0(cBlock);
|
||||
@ -5443,7 +5446,12 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
|
||||
else
|
||||
#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))
|
||||
{
|
||||
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,
|
||||
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,
|
||||
|
@ -453,7 +453,8 @@ static rem_port* inet_try_connect( PACKET*,
|
||||
const TEXT*,
|
||||
ClumpletReader&,
|
||||
RefPtr<Config>*,
|
||||
const PathName*);
|
||||
const PathName*,
|
||||
int);
|
||||
static bool inet_write(XDR*);
|
||||
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,
|
||||
ClumpletReader &dpb,
|
||||
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;
|
||||
switch (packet->p_operation)
|
||||
@ -708,7 +710,8 @@ rem_port* INET_connect(const TEXT* name,
|
||||
PACKET* packet,
|
||||
USHORT flag,
|
||||
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;
|
||||
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;
|
||||
|
||||
#if !defined(WIN_NT) && !defined(__clang__)
|
||||
@ -811,7 +817,7 @@ rem_port* INET_connect(const TEXT* name,
|
||||
|
||||
gai_hints.ai_flags =
|
||||
#ifndef ANDROID
|
||||
AI_V4MAPPED |
|
||||
((af == AF_UNSPEC) ? AI_V4MAPPED : 0) |
|
||||
#endif
|
||||
AI_ADDRCONFIG | (packet ? 0 : AI_PASSIVE);
|
||||
|
||||
@ -825,7 +831,8 @@ rem_port* INET_connect(const TEXT* name,
|
||||
retry_gai = false;
|
||||
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
|
||||
gai_hints.ai_family = AF_UNSPEC;
|
||||
@ -2639,7 +2646,8 @@ static rem_port* inet_try_connect(PACKET* packet,
|
||||
const TEXT* node_name,
|
||||
ClumpletReader& dpb,
|
||||
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;
|
||||
try
|
||||
{
|
||||
port = INET_connect(node_name, packet, false, &dpb, config);
|
||||
port = INET_connect(node_name, packet, false, &dpb, config, af);
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
|
@ -34,9 +34,10 @@ namespace Firebird
|
||||
}
|
||||
|
||||
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*,
|
||||
Firebird::RefPtr<Config>*);
|
||||
Firebird::RefPtr<Config>*, int af = AF_UNSPEC);
|
||||
rem_port* INET_reconnect(SOCKET);
|
||||
rem_port* INET_server(SOCKET);
|
||||
void setStopMainThread(FPTR_INT func);
|
||||
|
Loading…
Reference in New Issue
Block a user