Bug 53217 - SqlException is thrown when connecting through IPv6 network
Summary: SqlException is thrown when connecting through IPv6 network
Status: RESOLVED FIXED
Alias: None
Product: Class Libraries
Classification: Mono
Component: System.Data ()
Version: 4.6.0 (C8)
Hardware: Other Other
: --- normal
Target Milestone: Untriaged
Assignee: Egorbo
URL:
Depends on:
Blocks:
 
Reported: 2017-03-10 10:25 UTC by drveto
Modified: 2017-09-01 09:29 UTC (History)
2 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Test project for testing the issues (149.16 KB, application/x-zip-compressed)
2017-03-10 10:25 UTC, drveto
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description drveto 2017-03-10 10:25:43 UTC
Created attachment 20269 [details]
Test project for testing the issues

Description : 
When calling Open() on SqlConnection with an MS SQL database through an IPv6 network, a SqlException is thrown with the message 'Server does not exist or connection refused.'.
This occures in both Android and iOS devices connected to an IPv6 network. There is no problem when devices are connected to an IPv4 network. 

This issue is blocking with the Apple iOS validation process as they now test all submitted apps on an IPv6 network. 

Steps:

1- configure a NAT64 network on a Mac following these instructions : https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html

2- connect your iOS or Android device to the IPv6 created network

3- try opening a SqlConnection with a MS SQL database

Actual Results:
The SqlException is thrown.

Expected Results:
The SQL connection is successfully opened.

Build Date & Hardware:
Xamarin Studio: 6.1.5
Mono: 4.6.0
GTK+: 2.24.23
Apple dev tools: Xcode 8.2.1 (11766.1)
Xamarin.iOS: 10.3.1.8
Xamarin.Android: 7.0.2.42
Xamarin build station: Mac OS X 10.11.6

Additional Information:

When using SQL Studio Management from a Windows computer connected to this IPv6 network, we have no issue when connecting to our MS SQL server or executing SQL queries. 

After further investigations, the original exception seems to come from 'Mono.Data.Tds.Protocol/TdsComm' (https://github.com/mono/mono/blob/0bcbe39b148bb498742fc68416f8293ccd350fb6/mcs/class/Mono.Data.Tds/Mono.Data.Tds.Protocol/TdsComm.cs)
When opening the socket (line 108), it is badly configured. The AddressFamily is always defined as 'AddressFamily.InterNetwork' (IPv4): 

l108 : new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

It should probably use the 'AddressFamily' property of the IPAddress instance instead of always using the same enumeration value. 

The attached test solution contains an iOS project for testing these issues. The db parameters and ip addresses must be set in the iOS project directly in the class 'SqlService'. 
- SqlConnection.Open(): will try to open an SQL connection
- SocketV4: will simulate the 'new Socket()' action in TdsComm with the AddressFamily.InterNetwork value. It should return 'Socket V4 : error'.
- SocketV6: will simulate the 'new Socket()' with a fix for the correct AddressFamily. It should return 'Socket V6 : success'.
Comment 1 drveto 2017-03-28 08:16:06 UTC
We confirm that the bug is indeed in TdsComm. We have managed to get the SQL connection working by using this ugly fix: 

try
{
	socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
	IAsyncResult ares = socket.BeginConnect (endPoint, null, null);
	if (timeout > 0 && !ares.IsCompleted && !ares.AsyncWaitHandle.WaitOne (timeout_ms, false))
		throw Tds.CreateTimeoutException (dataSource, "Open()");
	socket.EndConnect (ares);
}
catch
{
	try
	{
		socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
		IAsyncResult ares = socket.BeginConnect (endPoint, null, null);
		if (timeout > 0 && !ares.IsCompleted && !ares.AsyncWaitHandle.WaitOne (timeout_ms, false))
			throw Tds.CreateTimeoutException (dataSource, "Open()");
		socket.EndConnect (ares);
	}
	catch (Exception ex)
	{
		throw ex;
	}
}
Comment 2 Egorbo 2017-03-28 08:57:42 UTC
@drveto fixed in master, endpoint.AddressFamily should be enough.