Информация о сетевых интерфейсах
Материал из 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