Запрос DHCP-сервера в C # - PullRequest
       47

Запрос DHCP-сервера в C #

8 голосов
/ 09 февраля 2010

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

Я понимаю, утилита netsh может быть использована для получения дампа, однако я не добился большого успеха с этим.

Какие-нибудь рабочие примеры или намек на это?

У меня есть права администратора на DHCP-сервере

Редактировать

Я не хочу использовать arp-кеш, поскольку для этого потребуется либо широковещательный пинг (который не разрешен в windows), либо пинг всех возможных ip-адресов подсети (что занимает много времени).

Я уверен, что DHCP-сервер хранит сопоставление MAC-адреса с IP-адресом. Как я могу использовать эту информацию для сопоставления MAC-адреса с IP-адресом?

Ответы [ 3 ]

4 голосов
/ 11 февраля 2010

Для этого вы можете использовать компонент DHCP Objects из Windows 2000 Resource Kit . Несмотря на то, что этот компонент трудно найти, он создан для Windows 2000, по словам Microsoft, в июле 2010 года он перестает работать, и у него очень мало документации, он работает.

  1. Загрузите Resource Kit Tool с именем DHCP Objects , например, здесь , если вы не можете найти его в Microsoft. Это даст вам файл .exe, который, в свою очередь, установит компонент DHCP Objects.
  2. Зарегистрируйте файл DHCPOBJS.DLL с помощью regsvr32 или , создайте для него приложение COM +. Что применимо, зависит от того, как COM-компонент будет использоваться в вашей системе.
  3. Используйте Импортер библиотек типов tlbimp.exe, чтобы создать управляемую оболочку около DHCPOBJS.DLL теперь, когда она зарегистрирована системой.
  4. В Visual Studio добавьте ссылку на управляемую оболочку. Сгенерированное по умолчанию имя - DhcpObjects.dll.

Теперь вы можете написать такой код для компонента:

using DhcpObjects;
class Program {
    static void Main(string[] args) {
        var manager = new Manager();
        var server = dhcpmgr.Servers.Connect("1.2.3.4");
        // query server here
    }
}

Установщик также предоставляет файл справки Windows, который содержит дополнительную документацию о том, как запрашивать и манипулировать сервером DHCP. Раздел «Модель объекта» весьма полезен.

1 голос
/ 13 октября 2010
using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.Net;

namespace dhcp
{
// c# class for processed clients

public class dhcpClient
{
    public string hostname { get; set; }
    public string ip       { get; set; }
    public string mac      { get; set; }
}

// structs for use with call to unmanaged code

[StructLayout(LayoutKind.Sequential)]
public struct DHCP_CLIENT_INFO_ARRAY
{
    public uint NumElements;
    public IntPtr Clients;
}

[StructLayout(LayoutKind.Sequential)]
public struct DHCP_CLIENT_UID
{
    public uint DataLength;
    public IntPtr Data;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct DHCP_CLIENT_INFO
{
    public uint ip;
    public uint subnet;

    public DHCP_CLIENT_UID mac;

    [MarshalAs(UnmanagedType.LPWStr)]
    public string ClientName;

    [MarshalAs(UnmanagedType.LPWStr)]
    public string ClientComment;
}

// main

class Program
{
    static void Main()
    {
        try
        {
            // get settings

            String server, subnet;

            Console.Write("Enter server : ");
            server = Console.ReadLine();
            Console.Write("Enter subnet : ");
            subnet = Console.ReadLine();

            // gather clients

            ArrayList clients = findDhcpClients(server, subnet);

            // output results

            Console.WriteLine();

            foreach (dhcpClient d in clients)
                Console.WriteLine(String.Format("{0,-35} {1,-15} {2,-15}", d.hostname, d.ip, d.mac));

            Console.WriteLine('\n' + clients.Count.ToString() + " lease(s) in total");
        }

        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }

        Console.ReadLine();
    }

    static ArrayList findDhcpClients(string server, string subnet)
    {
        // set up container for processed clients

        ArrayList foundClients = new ArrayList();

        // make call to unmanaged code

        uint parsedMask     = StringIPAddressToUInt32(subnet);
        uint resumeHandle   = 0;
        uint numClientsRead = 0;
        uint totalClients   = 0;

        IntPtr info_array_ptr;

        uint response = DhcpEnumSubnetClients(
            server,
            parsedMask,
            ref resumeHandle,
            65536,
            out info_array_ptr,
            ref numClientsRead,
            ref totalClients
            );

        // set up client array casted to a DHCP_CLIENT_INFO_ARRAY
        // using the pointer from the response object above

        DHCP_CLIENT_INFO_ARRAY rawClients =
            (DHCP_CLIENT_INFO_ARRAY)Marshal.PtrToStructure(info_array_ptr, typeof(DHCP_CLIENT_INFO_ARRAY));

        // loop through the clients structure inside rawClients 
        // adding to the dchpClient collection

        IntPtr current = rawClients.Clients;

        for (int i = 0; i < (int)rawClients.NumElements; i++)
        {
            // 1. Create machine object using the struct

            DHCP_CLIENT_INFO rawMachine =
                (DHCP_CLIENT_INFO)Marshal.PtrToStructure(Marshal.ReadIntPtr(current), typeof(DHCP_CLIENT_INFO));

            // 2. create new C# dhcpClient object and add to the 
            // collection (for hassle-free use elsewhere!!)

            dhcpClient thisClient = new dhcpClient();

            thisClient.ip = UInt32IPAddressToString(rawMachine.ip);

            thisClient.hostname = rawMachine.ClientName;

            thisClient.mac = String.Format("{0:x2}{1:x2}.{2:x2}{3:x2}.{4:x2}{5:x2}",
                Marshal.ReadByte(rawMachine.mac.Data),
                Marshal.ReadByte(rawMachine.mac.Data, 1),
                Marshal.ReadByte(rawMachine.mac.Data, 2),
                Marshal.ReadByte(rawMachine.mac.Data, 3),
                Marshal.ReadByte(rawMachine.mac.Data, 4),
                Marshal.ReadByte(rawMachine.mac.Data, 5));

            foundClients.Add(thisClient);

            // 3. move pointer to next machine

            current = (IntPtr)((int)current + (int)Marshal.SizeOf(typeof(IntPtr)));
        }

        return foundClients;
    }

    public static uint StringIPAddressToUInt32(string ip)
    {
        // convert string IP to uint IP e.g. "1.2.3.4" -> 16909060

        IPAddress i = System.Net.IPAddress.Parse(ip);
        byte[] ipByteArray = i.GetAddressBytes();

        uint ipUint = (uint)ipByteArray[0] << 24;
        ipUint += (uint)ipByteArray[1] << 16;
        ipUint += (uint)ipByteArray[2] << 8;
        ipUint += (uint)ipByteArray[3];

        return ipUint;
    }

    public static string UInt32IPAddressToString(uint ip)
    {
        // convert uint IP to string IP e.g. 16909060 -> "1.2.3.4"

        IPAddress i = new IPAddress(ip);
        string[] ipArray = i.ToString().Split('.');

        return ipArray[3] + "." + ipArray[2] + "." + ipArray[1] + "." + ipArray[0];
    }

    [DllImport("dhcpsapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern uint DhcpEnumSubnetClients(
            string ServerIpAddress,
            uint SubnetAddress,
        ref uint ResumeHandle,
            uint PreferredMaximum,
        out IntPtr ClientInfo,
        ref uint ElementsRead,
        ref uint ElementsTotal
    );
}
}
0 голосов
/ 09 февраля 2010

С помощью arp -a добьется цели ... на моей машине получится вывод:

У меня есть mac / ip-адрес, замененный поддельными значениями, чтобы показать результаты ...

C:\Documents and Settings\Tom>arp -a

Interface: 10.203.24.196 --- 0xf0007
  Internet Address      Physical Address      Type
  10.203.24.198         02-50-f3-10-14-06     dynamic

C:\Documents and Settings\Tom>

Обрабатывая System.Diagnostics.Process, вы можете перенаправить вывод во входной поток и читать из него ...

Надеюсь, это поможет, С наилучшими пожеланиями, Том.

...