Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access Violation on call to DsAddressToSiteNames #346

Closed
ryannewington opened this issue Nov 30, 2022 · 9 comments
Closed

Access Violation on call to DsAddressToSiteNames #346

ryannewington opened this issue Nov 30, 2022 · 9 comments

Comments

@ryannewington
Copy link

ryannewington commented Nov 30, 2022

Describe the bug and how to reproduce

When passing an array of SOCKET_ADDRESS to DsAddressToSiteNames either an access violation or win32 (1783) error (The stub received bad data) is throw.

What code is involved

The header for SOCKET_ADDRESS is as follows

[StructLayout(LayoutKind.Sequential,
#if x64
	Size = 16)]
#else
	Size = 8)]
#endif
	public struct SOCKET_ADDRESS

However, there appears to be no compiler definition for x64 and therefore, the layout size is always set to 8. If you compile your app to run 32-bit it succeeds. If you compile as AnyCPU or x64, it fails.

public struct SOCKET_ADDRESS

Changing this struct value manually works.

Expected behavior

The call should succeed on both x86 an x64 builds.

Repo sample

Modify the dcname variable below with the name of a domain controller to reproduce the issue.
Running as x64 fails, running as x86 succeeds

using System.Net;
using System.Runtime.InteropServices;
using Vanara.Extensions;
using Vanara.PInvoke;
using static Vanara.PInvoke.NetApi32;
using static Vanara.PInvoke.Ws2_32;

internal class Program
{
    private static void Main(string[] args)
    {
        string dcname = "dc1";

        Ws2_32.WSAStartup(2, out _);
        List<IPAddress> ipAddresses;

        try
        {
            // fails
            ipAddresses = new List<IPAddress>() { IPAddress.Parse("127.0.0.1"), IPAddress.Parse("::1") };
            GetSites(ipAddresses, dcname);
        }

        catch (Exception ex)
        {
            Console.WriteLine("lookup failed\r\n{0}", ex);
        }

        Console.WriteLine("=======================================================\r\n");

        try
        {
            // works
            ipAddresses = new List<IPAddress>() { IPAddress.Parse("127.0.0.1") };
            GetSites(ipAddresses, dcname);
        }
        catch (Exception ex)
        {
            Console.WriteLine("lookup failed\r\n{0}", ex);
        }

        Console.WriteLine("=======================================================\r\n");

        try
        {
            // works
            ipAddresses = new List<IPAddress>() { IPAddress.Parse("::1") };
            GetSites(ipAddresses, dcname);
        }
        catch (Exception ex)
        {
            Console.WriteLine("lookup failed\r\n{0}", ex);
        }

        Console.WriteLine("=======================================================\r\n");


        Console.WriteLine("press any key to exit");
        Console.ReadLine();
    }

    private static void GetSites(List<IPAddress> ipAddresses, string dcname)
    {
        List<Ws2_32.SOCKADDR> resolvedAddresses = new List<Ws2_32.SOCKADDR>();

        foreach (IPAddress ipAddress in ipAddresses.OrderBy(t => (int)t.AddressFamily))
        {
            Ws2_32.SOCKADDR socketAddress;

            if (ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
            {
                socketAddress = new Ws2_32.SOCKADDR_IN();
            }
            else if (ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
            {
                socketAddress = new Ws2_32.SOCKADDR_IN6();
            }
            else
            {
                Console.WriteLine("Ignoring unknown address type {0}", ipAddress.AddressFamily.ToString());
                continue;
            }

            int length = socketAddress.Size;
            string addr = ipAddress.ToString();

            var wsresult = Ws2_32.WSAStringToAddress(addr, (Ws2_32.ADDRESS_FAMILY)ipAddress.AddressFamily, IntPtr.Zero, socketAddress, ref length);

            if (wsresult.Failed)
            {
                Console.WriteLine("WSAStringToAddress failed\r\n{0}", wsresult.GetException());
            }

            resolvedAddresses.Add(socketAddress);
        }

        if (resolvedAddresses.Count == 0)
        {
            Console.WriteLine("No addresses found");
            return;
        }

        var socketAddresses = new SOCKET_ADDRESS[resolvedAddresses.Count];
        for (int i = 0; i < resolvedAddresses.Count; i++)
        {
            socketAddresses[i].iSockaddrLength = resolvedAddresses[i].Size;
            socketAddresses[i].lpSockaddr = resolvedAddresses[i].DangerousGetHandle();
        }

        NetApi32.SafeNetApiBuffer siteNames = null;

        var dsresult = DsAddressToSiteNames(dcname, (uint)socketAddresses.Length, socketAddresses, out siteNames);

        dsresult.ThrowIfFailed();

        if (siteNames == null || siteNames.IsInvalid)
        {
            Console.WriteLine("Sites were not found");
            return;
        }

        List<string> sites = siteNames.ToStringEnum(resolvedAddresses.Count).ToList();

        Console.WriteLine("Found sites {0} for addresses {1}", string.Join(", ", sites), string.Join(", ", ipAddresses));
    }
}
@ryannewington
Copy link
Author

Another note, this seems to have been introduced in a recent version. Downgrading to 3.2.16 and the problem goes away.

@dahall
Copy link
Owner

dahall commented Nov 30, 2022

Thank you for submitting such a thorough bug report! I'll have this resolved shortly.

@dahall
Copy link
Owner

dahall commented Dec 7, 2022

@ryannewington When you say "compile your app", how are you referencing the Vanara.PInvoke.Ws2_32 assembly? As a NuGet package or by directly including the code in your build?

@ryannewington
Copy link
Author

Hi David

That should say "compile my app". So this is using the NuGet package. If the sample app provided above, referencing the latest NuGet is compiled as x86 it works, x64 it fails.

I forked the library and modified the struct definition and could "fix" the issue by modifying the struct size.

@dahall
Copy link
Owner

dahall commented Dec 7, 2022

The problem lies in the AnyCPU platform selected for all the NuGet packages. I'm investigating if NuGet will allow me to provide both an AnyCPU build and an x64 build. More coming shortly after some more research.

@ryannewington
Copy link
Author

Oh right. I did notice that looking at the code of the version I downgraded to, there was no fixed size parameter on the struct. Is there an issue I should be aware of that adding the size fixed?

@dahall
Copy link
Owner

dahall commented Dec 8, 2022

Yes. The 32-bit size and 64-bit size are different. I have a few structures in Vanara that are like this, so I need to find a solution. I'll close this with comments when I get it resolved. Unfortunately, the documentation on NuGet packaging is pretty weak.

@dahall
Copy link
Owner

dahall commented Dec 20, 2022

Can you confirm that using v3.2.16 of the library has no problems even when compiling your exe under x64?

dahall added a commit that referenced this issue Dec 22, 2022
…e all structures work for both 32 and 64-bit (#346)
@dahall dahall closed this as completed Dec 22, 2022
@dahall
Copy link
Owner

dahall commented Dec 22, 2022

This is fixed with the latest commit. I'll publish soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants