private static void BuildIndexToInterfaceMap(NetworkInterface ni, SortedDictionary <uint, ArpTableDTO> adapters) { // We don't care about the loopback interface // if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback) return; var adapterProperties = ni.GetIPProperties(); if (adapterProperties == null) { throw new Exception("Could not get adapter IP properties"); } var index = (uint?)ni.GetType().GetField("index", BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(ni); if (index == null) { throw new Exception("Could not get interface index number"); } Console.WriteLine(ni.Description); var adapter = new ArpTableDTO(index.Value, ni.Name, ni.Description); adapterProperties.UnicastAddresses .ToList() .ForEach(ip => adapter.InterfaceIPs.Add(ip.Address.ToString())); adapterProperties.DnsAddresses .ToList() .ForEach(dns => adapter.DnsServers.Add(dns.ToString())); adapters.Add(index.Value, adapter); }
public override IEnumerable <CommandDTOBase?> Execute(string[] args) { // adapted from Fred's code at https://social.technet.microsoft.com/Forums/lync/en-US/e949b8d6-17ad-4afc-88cd-0019a3ac9df9/powershell-alternative-to-arp-a?forum=ITCG var adapterIdToInterfaceMap = new SortedDictionary <uint, ArpTableDTO>(); // build a mapping of index -> interface information foreach (var networkInterface in NetworkInterface.GetAllNetworkInterfaces()) { BuildIndexToInterfaceMap(networkInterface, adapterIdToInterfaceMap); } var bytesNeeded = 0; var result = Iphlpapi.GetIpNetTable(IntPtr.Zero, ref bytesNeeded, false); if (result != Win32Error.InsufficientBuffer) { throw new Exception($"GetIpNetTable: Expected insufficient buffer but got {result}"); } var buffer = Marshal.AllocCoTaskMem(bytesNeeded); try { result = Iphlpapi.GetIpNetTable(buffer, ref bytesNeeded, false); if (result != 0) { throw new Exception($"GetIpNetTable error: {result}"); } // now we have the buffer, we have to marshal it. We can read the first 4 bytes to get the length of the buffer var entries = Marshal.ReadInt32(buffer); // increment the memory pointer by the size of the int var currentBuffer = new IntPtr(buffer.ToInt64() + Marshal.SizeOf(typeof(int))); // allocate a list of entries var arpEntries = new List <Iphlpapi.MIB_IPNETROW>(); // cycle through the entries for (var index = 0; index < entries; index++) { arpEntries.Add((Iphlpapi.MIB_IPNETROW)Marshal.PtrToStructure( new IntPtr(currentBuffer.ToInt64() + (index * Marshal.SizeOf(typeof(Iphlpapi.MIB_IPNETROW)))), typeof(Iphlpapi.MIB_IPNETROW))); } // sort the list by interface index var sortedArpEntries = arpEntries.OrderBy(o => o.dwIndex).ToList(); uint?currentAdapterIndex = null; foreach (var arpEntry in sortedArpEntries) { var adapterIndex = (uint)arpEntry.dwIndex; if (currentAdapterIndex != adapterIndex) { if (!adapterIdToInterfaceMap.ContainsKey(adapterIndex)) { adapterIdToInterfaceMap[adapterIndex] = new ArpTableDTO(adapterIndex, "n/a", "n/a"); } currentAdapterIndex = adapterIndex; } var ipAddress = new IPAddress(BitConverter.GetBytes(arpEntry.dwAddr)); var macBytes = new[] { arpEntry.mac0, arpEntry.mac1, arpEntry.mac2, arpEntry.mac3, arpEntry.mac4, arpEntry.mac5 }; var physicalAddress = BitConverter.ToString(macBytes); var entryType = (Iphlpapi.ArpEntryType)arpEntry.dwType; var entry = new ArpEntry( ipAddress.ToString(), physicalAddress, entryType.ToString() ); adapterIdToInterfaceMap[adapterIndex].Entries.Add(entry); } } finally { if (buffer != IntPtr.Zero) { Iphlpapi.FreeMibTable(buffer); } } foreach (var adapter in adapterIdToInterfaceMap) { yield return(adapter.Value); } }