Description:
Testing the new RC of .NET connector I've found a regression from 1.0.7.
I'm unable to connect to *any* database. The problem seems to be related to IPv6.
The exception thrown at Open():
"Unable to connect to any of the specified MySQL hosts"
in MySql.Data.MySqlClient.NativeDriver.Open()
in MySql.Data.MySqlClient.Driver.Create(MySqlConnectionString settings)
in MySql.Data.MySqlClient.MySqlPool.CreateNewPooledConnection()
in MySql.Data.MySqlClient.MySqlPool.GetPooledConnection()
in MySql.Data.MySqlClient.MySqlPool.GetConnection()
in MySql.Data.MySqlClient.MySqlConnection.Open()
The inner exception is far more interesting ;)
"Address not compatible with the specified protocol" (my translation, I see the localized message, anyway error code is 10047).
in System.Net.Sockets.Socket.DoBeginConnect(EndPoint endPointSnapshot, SocketAddress socketAddress, LazyAsyncResult asyncResult)
in System.Net.Sockets.Socket.BeginConnect(EndPoint remoteEP, AsyncCallback callback, Object state)
in MySql.Data.Common.StreamCreator.CreateSocketStream(IPAddress ip, Int32 port, Boolean unix) in C:\Programmi\mysql\MySQL Connector Net 1.0.8\Source\MySqlClient\common\StreamCreator.cs:riga 134
in MySql.Data.Common.StreamCreator.GetStream(UInt32 timeOut) in C:\Programmi\mysql\MySQL Connector Net 1.0.8\Source\MySqlClient\common\StreamCreator.cs:riga 80
in MySql.Data.MySqlClient.NativeDriver.Open() in C:\Programmi\mysql\MySQL Connector Net 1.0.8\Source\MySqlClient\nativedriver.cs:riga 145
My analysis:
Connection string:
Host=localhost;Database=dbname;User Id=myuser;Password=pass
What I see is that StreamCreator.GetStream() gets the IP address(es) of the host using:
IPHostEntry ipHE = Dns.GetHostEntry(dnsHosts[index]);
(line 73)
On my system IPv6 networking is enabled, so the resulting address list contains IPv6 addresses and IPv4 address is the last of the list. Please note that I'm *not* trying to connect to a v6 address.
Afterwards StreamCreator.GetStream() pass down each address to CreateSocketStream() until one is successful. Problem is that inside CreateSocketStream() the socket is created using AF "InterNetwork" (lines 131-133); BeginConnect() is called on this socket using a v6 address and throws an exception. The outer loop cannot handle the exception which propagates back and prevent any connection.
1.0.7 does not exhibit this behaviour.
How to repeat:
string connStr = "Host=localhost;Database=dbname;User Id=myuser;Password=pass"
MySqlConnection conn = new MySqlConnection(connStr);
conn.Open();
IPv6 networking must be enabled.
Suggested fix:
Skip any IPv6 address returned by GetHostEntry. I've modified the loop in StreamCreator.GetStream() in this way:
foreach (IPAddress address in ipHE.AddressList)
{
/* Skip IPv6 addresses */
if (address.AddressFamily == AddressFamily.InterNetworkV6)
continue;
stream = CreateSocketStream(address, port, false);
if (stream != null)
break;
}
(I'd send a patch but I can't find a way to attach a file...)