Dưới đây là một lớp học cho thấy các cấu trúc cần thiết và làm thế nào để thực hiện cuộc gọi đến ResolveIpNetEntry2:
class ResolveMac
{
private const short AF_INET6 = 23;
#region Structs for ResolveIpNetEntry2
struct MIB_IPNET_ROW2
{
public SOCKADDR_INET Address;
public uint InterfaceIndex;
public ulong InterfaceLuid;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] PhysicalAddress;
public uint PhysicalAddressLength;
public NL_NEIGHBOR_STATE State;
public byte Flags;
public uint LastReachable;
}
private struct SOCKADDR_INET
{
public SOCKADDR_IN6 Ipv6;
}
private struct SOCKADDR_IN6
{
public short sin6_family;
public ushort sin6_port;
public uint sin6_flowinfo;
public in6_addr sin6_addr;
public uint sin6_scope_id;
}
struct in6_addr
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] Byte;
}
#endregion
private enum NL_NEIGHBOR_STATE
{
NlnsUnreachable,
NlnsIncomplete,
NlnsProbe,
NlnsDelay,
NlnsStale,
NlnsReachable,
NlnsPermanent,
NlnsMaximum
}
[DllImport("Iphlpapi.dll")]
private static extern int ResolveIpNetEntry2(ref MIB_IPNET_ROW2 Row,
ref SOCKADDR_INET SourceAddress);
public static byte[] GetMacFromIPv6Address(IPAddress ipv6Address)
{
if (ipv6Address.AddressFamily !=
System.Net.Sockets.AddressFamily.InterNetworkV6)
throw new ArgumentException(
"The IPAddress provided was not an IPv6 address.");
//set up target address
MIB_IPNET_ROW2 row2 = new MIB_IPNET_ROW2();
row2.PhysicalAddress = new byte[32];
row2.State = NL_NEIGHBOR_STATE.NlnsReachable;
row2.Address.Ipv6.sin6_addr.Byte = new byte[16];
row2.Address.Ipv6.sin6_family = AF_INET6;
row2.Address.Ipv6.sin6_flowinfo = 0;
row2.Address.Ipv6.sin6_port = 0;
row2.Address.Ipv6.sin6_scope_id = Convert.ToUInt32(ipv6Address.ScopeId);
byte[] ipv6AddressBytes = ipv6Address.GetAddressBytes();
System.Buffer.BlockCopy(ipv6AddressBytes, 0,
row2.Address.Ipv6.sin6_addr.Byte, 0, ipv6AddressBytes.Length);
//get this machine's local IPv6 address
SOCKADDR_INET sock = new SOCKADDR_INET();
sock.Ipv6.sin6_family = AF_INET6;
sock.Ipv6.sin6_flowinfo = 0;
sock.Ipv6.sin6_port = 0;
sock.Ipv6.sin6_addr.Byte = new byte[16];
IPAddress[] addresses = Dns.GetHostAddresses(Dns.GetHostName());
foreach (IPAddress address in addresses)
{
if (address.AddressFamily ==
System.Net.Sockets.AddressFamily.InterNetworkV6)
{
sock.Ipv6.sin6_addr.Byte = address.GetAddressBytes();
break;
}
}
foreach (NetworkInterface netInterface in
NetworkInterface.GetAllNetworkInterfaces())
{
if (netInterface.OperationalStatus == OperationalStatus.Up)
{
row2.InterfaceIndex = (uint)clsNetworkStats.GetInterfaceIndex(
netInterface.Description);
break;
}
}
int result = ResolveIpNetEntry2(ref row2, ref sock);
if (result != 0)
throw new ApplicationException(
"The call to ResolveIpNetEntry2 failed; error number: " +
result.ToString());
byte[] macAddress = new byte[6];
System.Buffer.BlockCopy(row2.PhysicalAddress, 0, macAddress, 0, 6);
return macAddress;
}
}
Về cơ bản, chỉ cần ping host mục tiêu, và thức ăn địa chỉ trở lại chức năng này.
Lớp clsNetworkStats được sử dụng để xác định InterfaceIndex sẽ được sử dụng. Tôi đã tìm thấy mã ví dụ này here và sửa đổi nó một chút.
internal class clsNetworkStats
{
// Fields
private const long ERROR_SUCCESS = 0L;
private ArrayList m_Adapters;
private const long MAX_INTERFACE_NAME_LEN = 0x100L;
private const long MAXLEN_IFDESCR = 0x100L;
private const long MAXLEN_PHYSADDR = 8L;
// Methods
public clsNetworkStats()
: this(true)
{
}
public clsNetworkStats(bool IgnoreLoopBack)
{
int lRetSize = 0;
MIB_IFROW ifrow = new MIB_IFROW();
byte[] buff = new byte[1];
byte val = 0;
long ret = GetIfTable(ref val, ref lRetSize, 0);
buff = new byte[lRetSize];
ret = GetIfTable(ref buff[0], ref lRetSize, 0);
int lRows = buff[0];
this.m_Adapters = new ArrayList(lRows);
byte len = (byte)lRows;
for (byte i = 1; i <= len; i++)
{
ifrow = new MIB_IFROW();
ifrow.dwIndex = Convert.ToUInt32(i);
ret = GetIfEntry(ref ifrow);
IFROW_HELPER ifhelp = this.PrivToPub(ifrow);
if (IgnoreLoopBack)
{
if (ifhelp.Description.IndexOf("Loopback") < 0)
{
this.m_Adapters.Add(ifhelp);
}
}
else
{
this.m_Adapters.Add(ifhelp);
}
}
}
public IFROW_HELPER GetAdapter(int index)
{
return (IFROW_HELPER)this.m_Adapters[index];
}
public int Count
{
get
{
return this.m_Adapters.Count;
}
}
[DllImport("iphlpapi")]
private static extern int GetIfEntry(ref MIB_IFROW pIfRow);
[DllImport("iphlpapi")]
private static extern int GetIfTable(ref byte pIfRowTable, ref int pdwSize, int bOrder);
//[DebuggerStepThrough]
private IFROW_HELPER PrivToPub(MIB_IFROW pri)
{
IFROW_HELPER ifhelp = new IFROW_HELPER();
ifhelp.Name = pri.wszName.Trim();
ifhelp.Index = Convert.ToInt32(pri.dwIndex);
ifhelp.Type = Convert.ToInt32(pri.dwType);
ifhelp.Mtu = Convert.ToInt32(pri.dwMtu);
ifhelp.Speed = Convert.ToInt32(pri.dwSpeed);
ifhelp.PhysAddrLen = Convert.ToInt32(pri.dwPhysAddrLen);
ifhelp.PhysAddr = Encoding.ASCII.GetString(pri.bPhysAddr);
ifhelp.AdminStatus = Convert.ToInt32(pri.dwAdminStatus);
ifhelp.OperStatus = Convert.ToInt32(pri.dwOperStatus);
ifhelp.LastChange = Convert.ToInt32(pri.dwLastChange);
ifhelp.InOctets = pri.dwInOctets; //Convert.ToInt32(pri.dwInOctets);
ifhelp.InUcastPkts = Convert.ToInt32(pri.dwInUcastPkts);
ifhelp.InNUcastPkts = Convert.ToInt32(pri.dwInNUcastPkts);
ifhelp.InDiscards = Convert.ToInt32(pri.dwInDiscards);
ifhelp.InErrors = Convert.ToInt32(pri.dwInErrors);
ifhelp.InUnknownProtos = Convert.ToInt32(pri.dwInUnknownProtos);
ifhelp.OutOctets = pri.dwOutOctets;//Convert.ToInt32(pri.dwOutOctets);
ifhelp.OutUcastPkts = Convert.ToInt32(pri.dwOutUcastPkts);
ifhelp.OutNUcastPkts = Convert.ToInt32(pri.dwOutNUcastPkts);
ifhelp.OutDiscards = Convert.ToInt32(pri.dwOutDiscards);
ifhelp.OutErrors = Convert.ToInt32(pri.dwOutErrors);
ifhelp.OutQLen = Convert.ToInt32(pri.dwOutQLen);
ifhelp.Description = Encoding.ASCII.GetString(pri.bDescr, 0, Convert.ToInt32(pri.dwDescrLen));
ifhelp.InMegs = this.ToMegs((long)ifhelp.InOctets);
ifhelp.OutMegs = this.ToMegs((long)ifhelp.OutOctets);
return ifhelp;
}
[DebuggerStepThrough]
private string ToMegs(long lSize)
{
string sDenominator = " B";
if (lSize > 0x3e8L)
{
sDenominator = " KB";
lSize = (long)Math.Round((double)(((double)lSize)/1000.0));
}
else if (lSize <= 0x3e8L)
{
sDenominator = " B";
// lSize = lSize;
}
return lSize.ToString("###,###") + sDenominator;
// (Strings.Format(lSize, "###,###0") + sDenominator);
}
// Nested Types
[StructLayout(LayoutKind.Sequential)]
public struct IFROW_HELPER
{
public string Name;
public int Index;
public int Type;
public int Mtu;
public int Speed;
public int PhysAddrLen;
public string PhysAddr;
public int AdminStatus;
public int OperStatus;
public int LastChange;
public uint InOctets; //changed
public int InUcastPkts;
public int InNUcastPkts;
public int InDiscards;
public int InErrors;
public int InUnknownProtos;
public uint OutOctets; //changed
public int OutUcastPkts;
public int OutNUcastPkts;
public int OutDiscards;
public int OutErrors;
public int OutQLen;
public string Description;
public string InMegs;
public string OutMegs;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct MIB_IFROW
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x100)]
public string wszName;
public uint dwIndex;
public uint dwType;
public uint dwMtu;
public uint dwSpeed;
public uint dwPhysAddrLen;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] bPhysAddr;
public uint dwAdminStatus;
public uint dwOperStatus;
public uint dwLastChange;
public uint dwInOctets;
public uint dwInUcastPkts;
public uint dwInNUcastPkts;
public uint dwInDiscards;
public uint dwInErrors;
public uint dwInUnknownProtos;
public uint dwOutOctets;
public uint dwOutUcastPkts;
public uint dwOutNUcastPkts;
public uint dwOutDiscards;
public uint dwOutErrors;
public uint dwOutQLen;
public uint dwDescrLen;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)]
public byte[] bDescr;
}
public static int GetInterfaceIndex(string description)
{
int val = 0;
clsNetworkStats stats = new clsNetworkStats();
for (int index = 0; index < stats.Count; index++)
{
string desc = stats.GetAdapter(index).Description;
if (desc == description + "\0")
{
val = stats.GetAdapter(index).Index;
break;
}
}
return val;
}
}