Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.07.25;
Скачать: CL | DM;

Вниз

Выявление "коллизий" в сети   Найти похожие ветки 

 
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 сомневаюсь что что-то получится) или через GetIfTable

const
 // Для работы с 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;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.025 c
1-1089723117
RedLord
2004-07-13 16:51
2004.07.25
установка RX Library 2.75 для Delphi 7


1-1089332816
NonProgrammer
2004-07-09 04:26
2004.07.25
Операции с датой


1-1089645134
ADMIN
2004-07-12 19:12
2004.07.25
system error. code 1447.


14-1089123566
sniknik
2004-07-06 18:19
2004.07.25
Диалог у монитора


14-1089012198
Terminator
2004-07-05 11:23
2004.07.25
И снова о женщинах...