Delphi: Obtenga MAC de enrutador
networking snmp (2)
Estoy usando Delphi y quiero determinar la dirección MAC física de un dispositivo de red en mi red, en este caso, el enrutador.
Mi código:
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;
donde 10.0.0.1 es mi enrutador
Por desgracia, QuickSend siempre envía "Restablecimiento de la conexión por el compañero # 10054". Traté de modificar el MIB-OID y también probé el IP 127.0.0.1 cuya conexión nunca debería fallar. No encontré Tutoriales utilizables sobre TIdSNMP en Google. :-(
Saludos Daniel Marschall
No queriendo robar el trueno de RRUZ, ofrezco la siguiente variante, tomada de mi base de código, con algunas observaciones. He hecho esto como una respuesta en lugar de un comentario para incluir el código.
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;
Hay un par de puntos para hacer.
No es necesario llamar a WSAStartup / WSACleanup.
EDITAR Como señala RRUZ en un comentario, la documentación winsock no exime explícitamente a inet_addr de WSAStartup / WSACleanup, así que me retracto de este punto. En Vista, es más simple simplemente llamar a RtlIpv4StringToAddress. Habiendo dicho todo eso, inet_addr es tan fácil de implementar que puede ser más fácil hacer el suyo.
En segundo lugar, la declaración de inet_addr en WinSock.pas es incorrecta. Declara que el valor de retorno es de un tipo u_long que se define en WinSock.pas como Entero largo. Este es un entero de 4 bytes con signo, pero debe ser un entero de 4 bytes sin signo, ULONG. Sin el reparto explícito, puedes obtener errores de rango.
Puede usar la función SendARP
para obtener la dirección Mac.
verifica esta muestra
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;