Delphi: получите MAC-адрес маршрутизатора - PullRequest
8 голосов
/ 29 декабря 2010

Я использую Delphi и хочу определить физический MAC-адрес сетевого устройства в моей сети, в данном случае сам маршрутизатор.

Мой код:

var
  idsnmp: tidsnmp;
  val:string;
begin
  idsnmp := tidsnmp.create;
  try
    idsnmp.QuickSend('.1.3.6.1.2.1.4.22.1.2', 'public', '10.0.0.1', val);
    showmessage(val);
  finally
    idsnmp.free;
  end;
end;

, где 10.0.0.1 - мой маршрутизатор.

Увы, QuickSend всегда отправляет «Сброс соединения по пиру # 10054». Я попытался изменить MIB-OID, и я также попробовал IP 127.0.0.1, соединение которого никогда не должно прерваться. Я не нашел никаких полезных Учебников о TIdSNMP в Google. : - (

С уважением Даниэль Маршалл

Ответы [ 2 ]

14 голосов
/ 29 декабря 2010

Вы можете использовать функцию SendARP для получения Mac-адреса.

проверьте этот образец

uses
 Windows,
 WinSock,
 SysUtils;


function SendArp(DestIP,SrcIP:ULONG;pMacAddr:pointer;PhyAddrLen:pointer) : DWord; StdCall; external 'iphlpapi.dll' name 'SendARP';


function GetMacAddr(const IPAddress: string; var ErrCode : DWORD): string;
var
MacAddr    : Array[0..5] of Byte;
DestIP     : ULONG;
PhyAddrLen : ULONG;
WSAData    : TWSAData;
begin
  Result    :='';
  WSAStartup($0101, WSAData);
  try
    ZeroMemory(@MacAddr,SizeOf(MacAddr));
    DestIP    :=inet_addr(PAnsiChar(IPAddress));
    PhyAddrLen:=SizeOf(MacAddr);
    ErrCode   :=SendArp(DestIP,0,@MacAddr,@PhyAddrLen);
    if ErrCode = S_OK then
     Result:=Format('%2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x',[MacAddr[0], MacAddr[1],MacAddr[2], MacAddr[3], MacAddr[4], MacAddr[5]])
  finally
    WSACleanup;
  end;
end;
5 голосов
/ 29 декабря 2010

Не желая красть гром RRUZ, я предлагаю следующий вариант, взятый из моей кодовой базы, с некоторыми наблюдениями.Я сделал это как ответ, а не как комментарий, чтобы включить код.

type
  TMacAddress = array [0..5] of Byte;

function inet_addr(const IPAddress: string): ULONG;
begin
  Result := ULONG(WinSock.inet_addr(PAnsiChar(AnsiString(IPAddress))));
end;

function SendARP(DestIP, SrcIP: ULONG; pMacAddr: Pointer; var PhyAddrLen: ULONG): DWORD; stdcall; external 'Iphlpapi.dll';

function GetMacAddress(const IPAddress: string): TMacAddress;
var
  MaxMacAddrLen: ULONG;
begin
  MaxMacAddrLen := SizeOf(Result);
  if SendARP(inet_addr(IPAddress), 0, @Result, MaxMacAddrLen)<>NO_ERROR then begin
    raise EMacAddressError.CreateFmt('Unable to do SendARP on address: ''%s''', [IPAddress]);
  end;
end;

Необходимо сделать пару замечаний.

Нет необходимости вызывать WSAStartup /WSACleanup.

EDIT Как указывает RRUZ в комментарии, документация winsock явно не освобождает inet_addr от WSAStartup / WSACleanup, поэтому я убираю эту точку зрения.В Vista проще просто вызвать RtlIpv4StringToAddress.Сказав все это, inet_addr настолько прост в реализации, что может быть проще накатить вашу собственную.

Во-вторых, объявление inet_addr в WinSock.pas неверно.Он объявляет возвращаемое значение типа u_long, который определен в WinSock.pas как Longint.Это 4-байтовое целое число со знаком, но оно должно быть 4-байтовым целым числом без знака, ULONG.Без явного приведения вы можете получить ошибки диапазона.

...