Example #1
0
        /// <summary>
        ///     Get the IP and MAC addresses of all known devices on the LAN
        /// </summary>
        /// <remarks>
        ///     1) This table is not updated often - it can take some human-scale time
        ///     to notice that a device has dropped off the network, or a new device
        ///     has connected.
        ///     2) This discards non-local devices if they are found - these are multicast
        ///     and can be discarded by IP address range.
        /// </remarks>
        /// <returns></returns>
        private static Dictionary <IPAddress, PhysicalAddress> GetAllDevicesOnLan()
        {
            var all = new Dictionary <IPAddress, PhysicalAddress> {
                { GetIpAddress(), GetMacAddress() }
            };

            // Add this PC to the list...
            var spaceForNetTable = 0;

            // Get the space needed
            // We do that by requesting the table, but not giving any space at all.
            // The return value will tell us how much we actually need.
            GetIpNetTable(IntPtr.Zero, ref spaceForNetTable, false);
            // Allocate the space
            // We use a try-finally block to ensure release.
            var rawTable = IntPtr.Zero;

            try
            {
                rawTable = Marshal.AllocCoTaskMem(spaceForNetTable);
                // Get the actual data
                var errorCode = GetIpNetTable(rawTable, ref spaceForNetTable, false);
                if (errorCode != 0)
                {
                    // Failed for some reason - can do no more here.
                    throw new Exception($"Unable to retrieve network table. Error code {errorCode}");
                }
                // Get the rows count
                var rowsCount     = Marshal.ReadInt32(rawTable);
                var currentBuffer = new IntPtr(rawTable.ToInt64() + Marshal.SizeOf(typeof(int)));
                // Convert the raw table to individual entries
                var rows = new MibIpnetrow[rowsCount];
                for (var index = 0; index < rowsCount; index++)
                {
                    rows[index] = (MibIpnetrow)Marshal.PtrToStructure(new IntPtr(currentBuffer.ToInt64() +
                                                                                 index *
                                                                                 Marshal.SizeOf(typeof(MibIpnetrow))
                                                                                 ),
                                                                      typeof(MibIpnetrow));
                }
                // Define the dummy entries list (we can discard these)
                var virtualMac   = new PhysicalAddress(new byte[] { 0, 0, 0, 0, 0, 0 });
                var broadcastMac = new PhysicalAddress(new byte[] { 255, 255, 255, 255, 255, 255 });
                foreach (var row in rows)
                {
                    var    ip     = new IPAddress(BitConverter.GetBytes(row.dwAddr));
                    byte[] rawMac = { row.mac0, row.mac1, row.mac2, row.mac3, row.mac4, row.mac5 };
                    var    pa     = new PhysicalAddress(rawMac);
                    if (!pa.Equals(virtualMac) && !pa.Equals(broadcastMac) && !IsMulticast(ip))
                    {
                        //Console.WriteLine("IP: {0}\t\tMAC: {1}", ip.ToString(), pa.ToString());
                        if (!all.ContainsKey(ip))
                        {
                            all.Add(ip, pa);
                        }
                    }
                }
            }
            finally
            {
                // Release the memory.
                Marshal.FreeCoTaskMem(rawTable);
            }
            return(all);
        }
Example #2
0
        public static List<string> GetRouterMac(string ipRequest = "192.168.1.1")
        {
            // The number of bytes needed.
            int bytesNeeded = 0;

            // The result from the API call.
            int result = GetIpNetTable(IntPtr.Zero, ref bytesNeeded, false);

            // Call the function, expecting an insufficient buffer.
            if (result != ErrorInsufficientBuffer)
            {
                // Throw an exception.
                throw new Win32Exception(result);
            }

            // Allocate the memory, do it in a try/finally block, to ensure
            // that it is released.
            IntPtr buffer = IntPtr.Zero;

            // Try/finally.
            try
            {
                // Allocate the memory.
                buffer = Marshal.AllocCoTaskMem(bytesNeeded);

                // Make the call again. If it did not succeed, then
                // raise an error.
                result = GetIpNetTable(buffer, ref bytesNeeded, false);

                // If the result is not 0 (no error), then throw an exception.
                if (result != 0)
                {
                    // Throw an exception.
                    throw new Win32Exception(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.
                int entries = Marshal.ReadInt32(buffer);

                // Increment the memory pointer by the size of the int.
                IntPtr currentBuffer = new IntPtr(buffer.ToInt64() +
                   Marshal.SizeOf(typeof(int)));

                // Allocate an array of entries.
                MibIpnetrow[] table = new MibIpnetrow[entries];

                // Cycle through the entries.
                for (int index = 0; index < entries; index++)
                {
                    // Call PtrToStructure, getting the structure information.
                    table[index] = (MibIpnetrow)Marshal.PtrToStructure(new
                       IntPtr(currentBuffer.ToInt64() + (index *
                       Marshal.SizeOf(typeof(MibIpnetrow)))), typeof(MibIpnetrow));
                }

                List<string> list = new List<string>();
                for (int index = 0; index < entries; index++)
                {
                    MibIpnetrow row = table[index];
                    IPAddress ip = new IPAddress(BitConverter.GetBytes(row.dwAddr));

                    StringBuilder sbMac = new StringBuilder();
                    sbMac.Append(row.mac0.ToString("X2") + '-');
                    sbMac.Append(row.mac1.ToString("X2") + '-');
                    sbMac.Append(row.mac2.ToString("X2") + '-');
                    sbMac.Append(row.mac3.ToString("X2") + '-');
                    sbMac.Append(row.mac4.ToString("X2") + '-');
                    sbMac.Append(row.mac5.ToString("X2"));

                    if (ip.ToString() == ipRequest)
                    {
                        list.Add(sbMac.ToString());
                    }
                }
                //if (list.Count == 0)
                //{
                //    throw new Exception("不存在的IP地址: " + ipRequest);
                //}
                return list;
            }
            finally
            {
                // Release the memory.
                FreeMibTable(buffer);
            }
        }