Как опросить сетевые устройства с помощью ARP-запроса?

Для опроса сетевых устройств с помощью ARP-запроса в C# необходимо использовать классы из пространства имен System.Net.NetworkInformation.

Прежде всего, нужно получить список всех устройств в локальной сети. Для этого используется класс NetworkInterface:

using System;
using System.Net.NetworkInformation;

class Program
{
    static void Main()
    {
        NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();

        foreach (NetworkInterface ni in interfaces)
        {
            if (ni.OperationalStatus == OperationalStatus.Up)
            {
                Console.WriteLine("Interface: {0}", ni.Name);

                IPInterfaceProperties ipProps = ni.GetIPProperties();
                foreach (UnicastIPAddressInformation ip in ipProps.UnicastAddresses)
                {
                    if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    {
                        Console.WriteLine("IP: {0}", ip.Address);
                    }
                }
            }
        }
    }
}

Получив список устройств, можно перебрать все возможные IP-адреса в локальной сети и отправить ARP-запрос каждому из них. Для этого используется класс Ping и его метод Send:

using System;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;

class Program
{
    static void Main()
    {
        NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();

        foreach (NetworkInterface ni in interfaces)
        {
            if (ni.OperationalStatus == OperationalStatus.Up)
            {
                IPInterfaceProperties ipProps = ni.GetIPProperties();
                foreach (UnicastIPAddressInformation ip in ipProps.UnicastAddresses)
                {
                    if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    {
                        byte[] macBytes = new byte[6];
                        new Random().NextBytes(macBytes);

                        IPAddress ipAddress = ip.Address;
                        IPAddress subnetMask = ip.IPv4Mask;

                        for (uint i = 2; i < 255; i++)
                        {
                            byte[] ipBytes = ipAddress.GetAddressBytes();
                            byte[] subnetBytes = subnetMask.GetAddressBytes();

                            byte[] targetBytes = new byte[4];
                            for (int j = 0; j < 4; j++)
                            {
                                targetBytes[j] = (byte)((ipBytes[j] & subnetBytes[j]) | (i & ~subnetBytes[j]));
                            }

                            IPAddress targetAddress = new IPAddress(targetBytes);

                            PingReply reply = new Ping().Send(targetAddress.ToString(), 1000);

                            if (reply.Status == IPStatus.Success)
                            {
                                Console.WriteLine("IP: {0}", reply.Address);
                                Console.WriteLine("MAC: {0}", GetMacAddress(reply.Address.ToString()));
                            }
                        }
                    }
                }
            }
        }
    }

    public static string GetMacAddress(string ipAddress)
    {
        ProcessStartInfo psi = new ProcessStartInfo("arp", "-a " + ipAddress);
        psi.RedirectStandardOutput = true;
        psi.UseShellExecute = false;
        psi.CreateNoWindow = true;

        Process p = Process.Start(psi);
        string output = p.StandardOutput.ReadToEnd();
        p.Close();

        int index = output.IndexOf(':');
        if (index != -1 && index + 3 < output.Length)
        {
            return output.Substring(index - 2, 17);
        }

        return null;
    }
}

Этот код проходит по всем устройствам в списке, получает IP-адреса и маски подсети, а затем перебирает все возможные IP-адреса в текущей подсети. Для каждого IP-адреса отправляется ARP-запрос с помощью Ping.Send, и, если получен ответ, выводится IP-адрес и MAC-адрес устройства.

Функция GetMacAddress использует команду arp -a для получения MAC-адреса устройства по его IP-адресу. Это сделано для того, чтобы получить MAC-адресы не только локальных устройств, но и устройств, находящихся в других подсетях.

Обратите внимание, что для выполнения данного кода требуются привилегии администратора, так как использование ARP-запросов требует определенных системных прав.