Информация о сетевых интерфейсах

Материал из DRKB


unit netinfo;

interface

uses Libc;

type
  INTERFACE_INFO = packed record
    Name: string;
    IPAddress: string;
    Broadcast: string;
    NetMask: string;
    IsUp: Boolean;
    IsRun: Boolean;
    IsBroadcast: Boolean;
    IsMulticast: Boolean;
    IsLoopBack: Boolean;
    IsPPP: Boolean;
  end;

  TAInfo = record
    INFO: array of INTERFACE_INFO;
  end;

function EnumInterfaces(var IInfo: TAInfo): Boolean;

implementation

function EnumInterfaces(var IInfo: TAInfo): Boolean;
var
  SHandle: Integer;
  len: LongInt;
  buf: PChar;
  ifc: ifconf;
  pifr: pifreq;
  ifr: ifreq;
  lastlen, i: Integer;
  pAddr: PChar;
begin
  Result := False;
  // создать UDP сокет
  SHandle := Socket(AF_INET, SOCK_DGRAM, 0);
  if SHandle = INVALID_SOCKET then exit;

{
При вызове SIOCGIFCONF некоторые реализации
не возвращают ошибок, если буфер слишком мал
для хранения результата вызова (результат просто обрезается)
Поэтому надо сделать вызов, запомнить возвращенную длину,
увеличить буфер и сделать еще один вызов
если после этого вызова длины будут равны - OK!
иначе надо циклично увеличивать буфер.
}
  lastlen := 0;
  len := 100 * SizeOf(ifreq);

  while True do
  begin
    buf := Malloc(len);
    ifc.ifc_len := len;
    PChar(ifc.ifc_ifcu) := buf;
    if ioctl(SHandle, SIOCGIFCONF, @ifc) < 0 then
    begin
      if (errno <> EINVAL) and (lastlen <> 0) then
        warn('ioctl error');
    end
    else
    begin
      if ifc.ifc_len = lastlen then break;
      lastlen := ifc.ifc_len;
    end;
    len := len + 10 * SizeOf(ifreq);
    Free(buf);
  end;
  Result := True;
  // здесь результат получен полностью
  // len - кол-во интерфейсов
  len := ifc.ifc_len div SizeOf(ifreq);
  SetLength(IInfo.Info, len);

  // указатель - на начало буфера
  pifr := ifc.ifc_ifcu.ifcu_req;
  for i := 0 to len - 1 do
  begin
    FillChar(ifr, SizeOf(ifreq), 0);
    // считать очередную порцию данных
    Move(pifr^, ifr, SizeOf(ifreq));

    // имя интерфейса
    IInfo.INFO[i].Name := ifr.ifrn_name;
    // адрес интерфейса
    pAddr := inet_ntoa(ifr.ifru_addr.sin_addr);
    IInfo.INFO[i].IPAddress := pAddr;

    // ШВ адрес
    ioctl(SHandle, SIOCGIFBRDADDR, @ifr);
    pAddr := inet_ntoa(ifr.ifru_netmask.sin_addr);
    IInfo.INFO[i].Broadcast := pAddr;

    // маска сети
    ioctl(SHandle, SIOCGIFNETMASK, @ifr);
    pAddr := inet_ntoa(ifr.ifru_netmask.sin_addr);
    IInfo.INFO[i].NetMask := pAddr;

    // флаги
    ioctl(SHandle, SIOCGIFFLAGS, @ifr);

    IInfo.INFO[i].IsUP := (ifr.ifru_flags and IFF_UP) = IFF_UP;
    IInfo.INFO[i].IsRun := (ifr.ifru_flags and IFF_RUNNING) = IFF_RUNNING;
    IInfo.INFO[i].IsBroadcast := (ifr.ifru_flags and IFF_BROADCAST) = IFF_BROADCAST;
    IInfo.INFO[i].IsLoopBack := (ifr.ifru_flags and IFF_LOOPBACK) = IFF_LOOPBACK;
    IInfo.INFO[i].IsPPP := (ifr.ifru_flags and IFF_POINTOPOINT) = IFF_POINTOPOINT;
    IInfo.INFO[i].IsMulticast := (ifr.ifru_flags and IFF_MULTICAST) = IFF_MULTICAST;

    inc(pifr);
  end;
end;

end.


Author: pve
Source: Взято с Исходников.Ru
ID: 04621