TalAloni / SMBLibrary

Free, Open Source, User-Mode SMB 1.0/CIFS, SMB 2.0, SMB 2.1 and SMB 3.0 server and client library
GNU Lesser General Public License v3.0
732 stars 185 forks source link

SMBClient cannot handle IPv6 address resolved by Dns.GetHostEntry(serverName) #114

Closed DavidErben closed 1 year ago

DavidErben commented 2 years ago

On a system where a hostname has a IPv6 and IPv4 address, the SMBClient.Connect method fails because the first element in the list is an IPv6 address which cannot be handled.

grafik

System.NotSupportedException: This protocol version is not supported. at System.Net.Sockets.Socket.Connect(IPAddress address, Int32 port) at SMBLibrary.Client.SMB2Client.ConnectSocket(IPAddress serverAddress, Int32 port) at SMBLibrary.Client.SMB2Client.Connect(IPAddress serverAddress, SMBTransportType transport) at SMBLibrary.Client.SMB2Client.Connect(String serverName, SMBTransportType transport)

Current implementation:

    public bool Connect(string serverName, SMBTransportType transport)
    {
        m_serverName = serverName;
        IPHostEntry hostEntry = Dns.GetHostEntry(serverName);
        if (hostEntry.AddressList.Length == 0)
        {
            throw new Exception(String.Format("Cannot resolve host name {0} to an IP address", serverName));
        }
        IPAddress serverAddress = hostEntry.AddressList[0];
        return Connect(serverAddress, transport);
    }

Can be fixed by specifying address family to get only IPv4 addresses:

    public bool Connect(string serverName, SMBTransportType transport)
    {
        m_serverName = serverName;
        IPHostEntry hostEntry = Dns.GetHostEntry(serverName, System.Net.Sockets.AddressFamily.InterNetwork);
        [...]
    }
TalAloni commented 2 years ago

Hi, Just to make sure I understand,

  1. You have a Connect overload allowing you to provide an IPAddress. so the issue is limited to the Connect overload that accepting a 'serverName', right?
  2. I see that the issue is with 'System.Net.Sockets.Socket.Connect(IPAddress address, Int32 port)', why is that so? is that method does not support IPv6 generally, or your system specifically have IPv6 issues?
DavidErben commented 2 years ago

Yes exactly, right now I have fixed it by resolving the IP address manually and then use the constructor with the IPAddress directly. I tried to connect from a Win 10 PC to a SMB server running on Windows as well (I think Win 7), so they should be able to handle IPv6, but it might be a problem with one of the machines and/or the network.

I was just curious that by default it will always pick the IPv6 address and if this intended.

TalAloni commented 2 years ago

theoretically you can have IPv6-only network. I believe that when the library is used under .NET Core 3.0+ on a machine supporting IPv6 there is no issue. There might be an issue here with earlier .NET Core / .NET Framework versions not fully supporting IPv6.

I'll consider whether the library should force IPv4 under such conditions.

DavidErben commented 2 years ago

I am using .NET 6, but it might be a network issue. So ok for me and I will resolve the IP manually for now. Thanks!

dveljanoski commented 1 year ago

I have same issue with Net core 6 when machine is using IPv6 and you try to connect with server name, //var host = System.Environment.MachineName; var host= "MyCompName01" bool isConnected = client.Connect(host, SMBTransportType.DirectTCPTransport);

this will throw error: System.NotSupportedException: This protocol version is not supported. at System.Net.Sockets.Socket.Connect(IPAddress address, Int32 port) at SMBLibrary.Client.SMB2Client.ConnectSocket(IPAddress serverAddress, Int32 port) at SMBLibrary.Client.SMB2Client.Connect(IPAddress serverAddress, SMBTransportType transport) at SMBLibrary.Client.SMB2Client.Connect(String serverName, SMBTransportType transport)

and if set machine to prefer ipv4 then connection by server name is successful, any solution for this how to handle this because not always is possible to configure usage of version of ip address?

TalAloni commented 1 year ago

The solution suggested was to manually resolve the hostname to IPv4 and use the overload allowing to specify IPAddress.

I guess we can update the code to prefer IPv4 if both IPv4 and IPv6 are available

TalAloni commented 1 year ago

The code was updated to prefer IPv4 if both IPv4 and IPv6 are available, the change will be part of the upcoming v1.5.0.