Форум: "Сети";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
ВнизВыявление "коллизий" в сети Найти похожие ветки
← →
diMAN (2004-05-25 19:25) [0]У нас на предприятии закупили партию компьютеров у которых сетевые карты имеют одинаковый MAC-адрес, а т.к. все эти компьютеры выходят в локальную сеть, то пришлось вручную перенастраивать MAC-адреса, чтобы они были уникальными и могли через DHCP-сервер получить уникальные IP-адреса. Но время от времени в локальной сети выявляются компьютеры, имеющие одинаковые IP-адреса, вследствии одинаковых MAC-адресов. Толи не все компьютеры были первоначально нами перенастроены, толи пользователи переставили Windows, грохнув наши настройки, но проблема существует.
Хотелось бы узнать как можно програмным путём вычислить такие "проблемные" компьютеры? Я так думаю что нужно посылать ARP-пакет и вслучае прихода двух или более ответов считать что этот ip-адрес проблемный.
← →
Rouse_ © (2004-05-25 21:31) [1]Если карты Реалтековские (а насколько я знаю, только они поддерживают перепрошивку МАС) то просто сделай у каждой разные МАС и все...
Ты же сам сказал: > пришлось вручную перенастраивать MAC-адреса так в чем проблема?
А ARP получишь посредством SendARP (правда при битом IP сомневаюсь что что-то получится) или через GetIfTableconst
// Для работы с ARP (Address Resolution Protocol) таблицей
IPHLPAPI = "IPHLPAPI.DLL";
MAX_ADAPTER_ADDRESS_LENGTH = 7;
type
// Следующие три типа используются для работы с Iphlpapi.dll
// Выдрал из Iphlpapi.h
// Так будет выглядеть МАС
TMacAddress = array[0..MAX_ADAPTER_ADDRESS_LENGTH] of byte;
// Это структура для единичного запроса
TMibIPNetRow = packed record
dwIndex : DWORD;
dwPhysAddrLen : DWORD;
bPhysAddr : TMACAddress; // Вот здесь и лежит МАС!!!
dwAddr : DWORD;
dwType : DWORD;
end;
// Как и в статье не будем выделять память динамически,
// а сразу создадим массив... (хотя, чесно говоря, это не правильно,
// но я иду простым путем :)
TMibIPNetRowArray = array [0..512] of TMibIPNetRow;
// А это, как и во всей библиотеке, такая вот...
// запрашиваемая структура (в моей статье уже видел пример...)
PTMibIPNetTable = ^TMibIPNetTable;
TMibIPNetTable = packed record
dwNumEntries : DWORD;
Table: TMibIPNetRowArray;
end;
// Из всех приведенных функций эта самая интересная.
// Я много раз говорил о незаслуженном невнимании программистов
// к IPHLPAPI.DLL. Данный пример подтверждает это. На всех форумах
// можно услышать о получании МАС адреса посредством посылки IPX пакета
// и разбора заголовка ответа от удаленного компьютера
// (что само по себе геморой, если не принимать во внимание,
// что IPX уже практически вымер, и его мало где встретишь).
// Здесь же строится полная ARP таблица, на основании которой мы
// можем спокойно произвести выборку по нужному IP адресу,
// а так как все берется из кэша, то мы сможем узнать МАС адреса
// даже выключенных компьютеров...
// Единственный минус: в таблице (не всегда) отсутсвует информация
// по локальному компьютеру, т.е. таким образом можно получить
// все МАС адреса за исключением своего,
// но для этого есть уже другие функции...
// Приведу выдержку из MSDN:
// You can use IP Helper to perform Address Resolution Protocol (ARP) operations for the local computer.
// Use the following functions to retrieve and modify the ARP table.
// The GetIpNetTable retrieves the ARP table.
// The ARP table contains the mapping of IP addresses to physical addresses.
// Physical addresses are sometimes referred to as Media Access Controller (MAC) addresses.
// Хочу заметить что для NT есть очень интересная функция SendARP - позволяющая
// напрямую получить требуемый МАС без построения таблицы, поэтому советую
// модифицировать код программы для более эффективного исполнения участков кода
// под различными системами.
function TMainForm.GetMacFromIP(const IP: String): String;
// (Будем использовать функцию приведения из статьи)
// В качестве первого значения массив, второе значение,
// размер данных в массиве
function GetMAC(Value: TMacAddress; Length: DWORD): String;
var
I: Integer;
begin
if Length = 0 then Result := "00-00-00-00-00-00" else
begin
Result := "";
for i:= 0 to Length -2 do
Result := Result + IntToHex(Value[i], 2) + "-";
Result := Result + IntToHex(Value[Length-1], 2);
end;
end;
// Получаем IP адрес, заметь в отличии от работы с классом WC_IPADDRESS
// здесь преобразование идет в обратном порядке!
function GetDottedIPFromInAddr(const InAddr: Integer): String;
begin
Result := "";
Result := IntToStr(FOURTH_IPADDRESS(InAddr));
Result := Result + "." + IntToStr(THIRD_IPADDRESS(InAddr));
Result := Result + "." + IntToStr(SECOND_IPADDRESS(InAddr));
Result := Result + "." + IntToStr(FIRST_IPADDRESS(InAddr));
end;
// Основная функция
var
Table: TMibIPNetTable;
Size: Integer;
CatchIP: String;
Err, I: Integer;
begin
Result := RES_UNKNOWN;
Size := SizeOf(Table); // Ну тут все просто...
Err := GetIpNetTable(@Table, @Size, False); // Выполняем...
if Err <> NO_ERROR then // Проверка на ошибку...
begin
MessageDlg(ERR_MAC, mtError, [mbOK], 0);
Exit;
end;
// Теперь мы имеем таблицу из IP адресов и соответсвующих им MAC адресов
for I := 0 to Table.dwNumEntries - 1 do // Ищем нужный IP ...
begin
CatchIP := GetDottedIPFromInAddr(Table.Table[I].dwAddr);
if CatchIP = IP then // И выводим его МАС ...
begin
Result := GetMAC(Table.Table[I].bPhysAddr, Table.Table[I].dwPhysAddrLen);
Break;
end;
end;
end;
procedure TMainForm.GetShares(const CompName: String);
var
Enum, I: Cardinal;
ScanRes: array [0..512] of TNetResource; // Можно сделать и больший размер массива
Size, Entries, Err: DWORD; // но, как показывает практика, такого достаточно
CurrRes: TNetResource;
ParentName: array [0..1] of TNetResource;
Str: PChar;
begin
with CurrRes do
begin
dwScope := RESOURCE_GLOBALNET;
dwType := RESOURCETYPE_DISK;
dwDisplayType := RESOURCEDISPLAYTYPE_SERVER;
dwUsage := RESOURCEUSAGE_CONTAINER;
lpLocalName := "";
lpRemoteName := PChar("\\ROUSE");
lpComment := "";
lpProvider := nil;
end;
Size := SizeOf(ScanRes);
Entries := DWORD(-1);
WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, @CurrRes, Enum);
Err := WNetEnumResource(Enum, Entries, @ScanRes, Size);
Caption := ScanRes[0].lpRemoteName;
// ParentName[0].lpProvider;
end;
---
Желаю успехов
← →
Rouse_ © (2004-05-25 21:34) [2]procedure TMainForm.GetShares(const CompName: String);
это я захватил лишнего, к основному примеру данная процедура не имеет никакого отношения ;)
← →
Rouse_ © (2004-05-25 21:36) [3]Да забыл: ARP таблица строится динамически и время ее жизДни примерно 30 сек. поэтому желательно пропинговать удаленную машину, но это тоже может оказаться проблематичным с битым IP :)
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.047 c