views:

219

answers:

1

I'm attempting to rewrite some C# web service code that uses the Windows IP Helper API call "SendARP" to retreive a remote system's MAC address. SendARP works great - until you cross a network segment as Arp requests aren't routed. I've been looking at the "ParseNetworkString" documentation after happening across its existance on StackOverflow. The quick & dirty algorithm I have in mind is:

public static string GetMacAddress(string strHostOrIP) 
{
    if (strHostOrIP is IPAddress)
    {
        parse results of nbstat -A strHostOrIP
        return macAddress
    }
    if (strHostOrIP is Hostname)
    {
        IPHostEntry hostEntry = null;
        try 
        { 
            hostEntry = Dns.GetHostEntry(strHostOrIP); 
        }
        catch 
        { 
            return null; 
        }
        if (hostEntry.AddressList.Length == 0) 
        { 
            return null; 
        }
        foreach (IPAddress ip in hostEntry.AddressList) 
        {
            if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
            {
                ipAddress = ip;
                break;
            }
        }
    }
    return GetMACAddress(ipAddress);

}

"ParseNetworkString" is new with Vista/Win2008 so I haven't been able to find example C# code demonstrating its use and I'm no C++ coder so if anyone can point me in the right direction...

A: 

Try this: (Untested)

[DllImport("IpHlpApi.dll", Charset = Charset.Unicode)]
static int ParseNetWorkString(ref string networkString, int types, out NetAddressInfo addressInfo, out ushort portNumber, out byte prefixLength);

[StructLayout(LayoutKind.Sequential)]
struct NamedAddress {
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)] //DNS_MAX_NAME_BUFFER_LENGTH
    public string Address;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
    public string Port;
}
[StructLayout(LayoutKind.Explicit)]
struct NetAddressInfo {
    public int Format;    //I'm too lazy to port the enum; you should

    [FieldOffset(4)]
    public NamedAddress NamedAddress;
    [FieldOffset(4)]
    public SOCKADDR_IN Ipv4Address;
    [FieldOffset(4)]
    public SOCKADDR_IN6 Ipv6Address;
    [FieldOffset(4)]
    public SOCKADDR IpAddress;
}

You should make the types parameter an enum; I'm too lazy. You'll also need to port the SOCKADDR_IN, SOCKADDR_IN6, and SOCKADDR structures.

SLaks