Bardo:如何得知远程机器的MAC地址(并且不是代理的)?
kaneboy:我感觉没有任何方法,因为proxy的作用就是用proxy server去取数据,局域网内的电脑是不会直接和外面相 连的。即使是能透过proxy的http协议,也不能传递mac信息。要不要我将JAVA的方法贴你看?
wwwunix:呵呵,容易呀,向远程机发一个arp查询包就行了。如果他是通过代理上网,则根据网络的原理,除非在远程机器上装个服务,否则一般不能得到它的MAC。SendArp函数无法越过代理与防火墙,如何是好?
Bardo:偏偏有个调用Java Applet的JAVA程序就做到了,他是在吹牛?
wwwunix:Java Applet是在客户机上运行的程序,不是在服务器上运行的。所以Java Applet可以获取。首先用普通方法是不行的(除了能在client端运行程序),我们可以看看TCP/IP的实现原理:
1、任何一个IP通讯都要事先知道对方的MAC地址,如果不知道则先发送一个ARP请求来获取对方的MAC地址。
2、在同一网络的通讯很简单就不说了。
3、如果ARP请求是从一个网络的主机发往另一个网络上的主机,那么连接这两个网络的路由器就回答该请求, 并把自己的MAC告诉请求方。这样请求方就会认为路由器就是目标主机而将IP包发给这个路由器,从而让路由器 转发。(这样路由器也就滤掉了ARP请求包)
用SNMP的话,可能可以实现,我对SNMP不熟,不敢肯定。
Bardo:以下是一个实现者的参考:
我们可以通过好几种方法来调用SNMP代理,如用C++来调用WINT下SNMP自带的SNMP API FOR WIN32的动态链接 库,也可以利用SNMP PERL来编写CGI程序完成这种功能,也可以用SNMP Java程序来编写。SNMP Java程序类似 于SNMP PERL程序,它是Java程序类扩展库,它提供了Java语言与SNMP代理接口的类库,使程序员通过调用这个 类库很容易地操纵SNMP代理,获取网络路由表中储存的网络设备的各种信息;包括IP地址与MAC地址映射表。下 面我介绍一下SNMP Java获取MAC信息的过程。首先在程序开头加SNMP Jva的扩展类,import Snmp. *;
……
OIDStr[0]=new String
(".1.3.6.1.2.1.3.1.1.2.0.0.1.47."+args[1]);定义IP地址与CAC地址的映射的位置
……
api=new SnmpAPI(); //产生一个SNMP代理的接口api. Start();
snmpPDU pdu=new SnmpPDU(api);
pdu. Command=apiGET_REQ_MSG;
SnmpSEssion session=new SnmpSession(api);
Session. version=SnmpAPI. SNMP VERSION_1;
Session. Peername=Host[I];//把路由器地址赋给线程SnmpOID odi=new SnmpOID(OIDStr[I], api); //产生 一个对象标识符
If(oid. ToValue()!=null)pdu. AddNull(oid);
Try{Session. Open();
Pdu=session. SyncSend(pdu);//发出请求单元信息}catch (SnmpException e){}
If (pdu= =null){//timeout
System. Out. Println("Request timed out to:"+Host);
System. Exit(1):}
SnmpVarBind Varbind=(SnmpVarBind)
Pdu. Variables. FirstElement();//找到第一满足条件的信息
PduStr=varbind. ToString();//存放找到的所需的信息
四、通过编写CGI程序实现SNMP代理功能
我们用Java编写一个sn.java程序,该程序的功能是根据给定的路由器地址(10.142.168.29)和主机IIP地址来 获得相应IP地址主机的MAC地址,如:java sn 10.142.168.29 10.142.169.1就会获得10.142.169.1的MAC地址 ,再通过编写一个C语言的CGI程序把Java程序执行的结果读取过来,和原有的合法MAC地址库中的数据进行比较 来验证用户是否佥。首先我们可通过读取环境变量"REMOTEADDR",该变量存放着请求用户工作站的IP地址, 作为执行Java程序的一个参数,再通过C语言的sprint函数来执行Java程序sn: Sprint(getmac, "java % s % s", 10.142.168.29. remote ipaddress);当C语言程序执行这个函数时,Java程序就被执行。并且getmac所 指向的文件头就是执行结果的文件头,我们再来读取该文件,就可获取remote ipaddress所对应的MAC地址,然 后可用这个MAC地址与原有的合法MAC地址库中数据相比较,从而验证用户是否为合法用户。
上面JAVA程序是用Snmp实现的,所以这里提供Snmp 所有API函数及常数的声明:
还望各献技!谢谢!
' Limits
Global Const MAXOBJIDSIZ% = 128
Global Const MAXOBJIDSTRSIZE = 1408
' ASN/BER base types
Global Const ASN_UNIVERSAL = &H0
Global Const ASN_APPLICATION = &H40
Global Const ASN_CONTEXT = &H80
Global Const ASN_PRIVATE = &HC0
Global Const ASN_PRIMITIVE = &H0
Global Const ASN_CONSTRUCTOR = &H20
' SNMP ObjectSyntax values
Global Const SNMP_SYNTAX_SEQUENCE = ASN_UNIVERSAL Or ASN_CONSTRUCTOR Or &H10
' 0xB0
' These values are used in the "syntax" member of VALUEs
Global Const SNMP_SYNTAX_INT = ASN_UNIVERSAL Or ASN_PRIMITIVE Or 2
' 0x02
Global Const SNMP_SYNTAX_BITS = ASN_UNIVERSAL Or ASN_PRIMITIVE Or 3
' 0x03
Global Const SNMP_SYNTAX_OCTETS = ASN_UNIVERSAL Or ASN_PRIMITIVE Or 4
' 0x04
Global Const SNMP_SYNTAX_NULL = ASN_UNIVERSAL Or ASN_PRIMITIVE Or 5
' 0x05
Global Const SNMP_SYNTAX_OID = ASN_UNIVERSAL Or ASN_PRIMITIVE Or 6
' 0x06
Global Const SNMP_SYNTAX_INT32 = SNMP_SYNTAX_INT
Global Const SNMP_SYNTAX_IPADDR = ASN_APPLICATION Or ASN_PRIMITIVE Or 0
' 0x40
Global Const SNMP_SYNTAX_CNTR = ASN_APPLICATION Or ASN_PRIMITIVE Or 1
' 0x41
Global Const SNMP_SYNTAX_GAUGE = ASN_APPLICATION Or ASN_PRIMITIVE Or 2
' 0x42
Global Const SNMP_SYNTAX_TIMETICKS = ASN_APPLICATION Or ASN_PRIMITIVE Or 3
' 0x43
Global Const SNMP_SYNTAX_OPAQUE = ASN_APPLICATION Or ASN_PRIMITIVE Or 4
' 0x44
Global Const SNMP_SYNTAX_NSAPADDR = ASN_APPLICATION Or ASN_PRIMITIVE Or 5
' 0x45
Global Const SNMP_SYNTAX_CNTR64 = ASN_APPLICATION Or ASN_PRIMITIVE Or 6
' 0x46
Global Const SNMP_SYNTAX_UINT32 = ASN_APPLICATION Or ASN_PRIMITIVE Or 7
' 0x47
' Exception conditions in response PDUs for SNMPv2
Global Const SNMP_SYNTAX_NOSUCHOBJECT = ASN_CONTEXT Or ASN_PRIMITIVE Or 0
' 0x80
Global Const SNMP_SYNTAX_NOSUCHINSTANCE = ASN_CONTEXT Or ASN_PRIMITIVE Or 1
' 0x81
Global Const SNMP_SYNTAX_ENDOFMIBVIEW = ASN_CONTEXT Or ASN_PRIMITIVE Or 2
' 0x82
' PDU choices:
Global Const SNMP_PDU_GET = ASN_CONTEXT Or ASN_CONSTRUCTOR Or 0
' 0xA0
Global Const SNMP_PDU_GETNEXT = ASN_CONTEXT Or ASN_CONSTRUCTOR Or 1
' 0xA1
Global Const SNMP_PDU_RESPONSE = ASN_CONTEXT Or ASN_CONSTRUCTOR Or 2
' 0xA2
Global Const SNMP_PDU_SET = ASN_CONTEXT Or ASN_CONSTRUCTOR Or 3
' 0xA3
' SNMP_PDU_V1TRAP is obsolete in SNMPv2
Global Const SNMP_PDU_V1TRAP = ASN_CONTEXT Or ASN_CONSTRUCTOR Or 4
' 0xA4
Global Const SNMP_PDU_GETBULK = ASN_CONTEXT Or ASN_CONSTRUCTOR Or 5
' 0xA5
Global Const SNMP_PDU_INFORM = ASN_CONTEXT Or ASN_CONSTRUCTOR Or 6
' 0xA6
Global Const SNMP_PDU_TRAP = ASN_CONTEXT Or ASN_CONSTRUCTOR Or 7
' 0xA7
' SNMP error codes returned in Error_Status field of PDU
' (these are NOT WinSNMP API error codes!)
Global Const SNMP_ERROR_NOERROR = 0
Global Const SNMP_ERROR_TOOBIG = 1
Global Const SNMP_ERROR_NOSUCHNAME = 2
Global Const SNMP_ERROR_BADVALUE = 3
Global Const SNMP_ERROR_READONLY = 4
Global Const SNMP_ERROR_GENERR = 5
' Error codes added for SNMPv2
Global Const SNMP_ERROR_NOACCESS = 6
Global Const SNMP_ERROR_WRONGTYPE = 7
Global Const SNMP_ERROR_WRONGLENGTH = 8
Global Const SNMP_ERROR_WRONGENCODING = 9
Global Const SNMP_ERROR_WRONGVALUE = 10
Global Const SNMP_ERROR_NOCREATION = 11
Global Const SNMP_ERROR_INCONSISTENTVALUE = 12
Global Const SNMP_ERROR_RESOURCEUNAVAILABLE = 13
Global Const SNMP_ERROR_COMMITFAILED = 14
Global Const SNMP_ERROR_UNDOFAILED = 15
Global Const SNMP_ERROR_AUTHORIZATIONERROR = 16
Global Const SNMP_ERROR_NOTWRITABLE = 17
Global Const SNMP_ERROR_INCONSISTENTNAME = 18
' Trap generic types:
Global Const SNMP_TRAP_COLDSTART = 0
Global Const SNMP_TRAP_WARMSTART = 1
Global Const SNMP_TRAP_LINKDOWN = 2
Global Const SNMP_TRAP_LINKUP = 3
Global Const SNMP_TRAP_AUTHFAIL = 4
Global Const SNMP_TRAP_EGPNEIGHBORLOSS = 5
Global Const SNMP_TRAP_ENTERPRISESPECIFIC = 6
' Type declarations:
'
' WinSNMP Descriptors
Type OID
len As Long
ptr As Long
End Type
Type OCTET ' Also: BITS, IPADDR, OPAQUE & NSAPADDR
len As Long
ptr As Long
End Type
Type OCTETSTRING
len As Long
ptr As String
End Type
Type CNTR64
' This is not a "Descriptor", but is a structure
' which can be used in a VALUE
hiPart As Long
loPart As Long
End Type
' WinSNMP Variable Binding "VALUE" definitions
Type VALUEINT
' Also INT32, UINT32, CNTR32, GAUGE32 & TIMETICKS
syntax As Long
long As Long
filler As Long 'To bring length up to 12 bytes
End Type
Type VALUECNTR64
syntax As Long
hNumber As CNTR64
End Type
Type VALUEOCTET
' Also BITS, OPAQUE, IPADDR & NSAPADDR
syntax As Long
octetv As OCTET
End Type
Type VALUEOID
syntax As Long
oidv As OID
End Type
' WinSNMP API values
'
' Values used to indicate entity/context translation modes
Global Const SNMPAPI_TRANSLATED = 0
Global Const SNMPAPI_UNTRANSLATED_V1 = 1
Global Const SNMPAPI_UNTRANSLATED_V2 = 2
' Values used to indicate SNMP "communications level"
' supported by the implementation
Global Const SNMPAPI_NO_SUPPORT = 0
Global Const SNMPAPI_V1_SUPPORT = 1
Global Const SNMPAPI_V2_SUPPORT = 2
Global Const SNMPAPI_M2M_SUPPORT = 3
' Values used to indicate retransmit mode in the implementation
Global Const SNMPAPI_OFF = 0
Global Const SNMPAPI_ON = 1
' WinSNMP API Function Return Codes
Global Const SNMPAPI_FAILURE = 0
Global Const SNMPAPI_SUCCESS = 1
' WinSNMP API Error Codes (for SnmpGetLastError())
' (NOT PDU error status codes)
Global Const SNMPAPI_ALLOC_ERROR = 2 'Error allocating memory
Global Const SNMPAPI_CONTEXT_INVALID = 3 'Invalid context parameter
Global Const SNMPAPI_CONTEXT_UNKNOWN = 4 'Unknown context parameter
Global Const SNMPAPI_ENTITY_INVALID = 5 'Invalid entity parameter
Global Const SNMPAPI_ENTITY_UNKOWN = 6 'Unknown entity parameter
Global Const SNMPAPI_INDEX_INVALID = 7 'Invalid VBL index parameter
Global Const SNMPAPI_NOOP = 8 'No operation performed
Global Const SNMPAPI_OID_INVALID = 9 'Invalid OID parameter
Global Const SNMPAPI_OPERATION_INVALID = 10 'Invalid/unsupported operation
Global Const SNMPAPI_OUTPUT_TRUNCATED = 11 'Insufficient output buffer length
Global Const SNMPAPI_PDU_INVALID = 12 'Invalid PDU parameter
Global Const SNMPAPI_SESSION_INVALID = 13 'Invalid session parameter
Global Const SNMPAPI_SYNTAX_INVALID = 14 'Invalid syntax in smiVALUE variable
Global Const SNMPAPI_VBL_INVALID = 15 'Invalid VBL parameter
Global Const SNMPAPI_MODE_INVALID = 16 'Invalid mode parameter
Global Const SNMPAPI_SIZE_INVALID = 17 'Invalid size/length parameter
Global Const SNMPAPI_NOT_INITIALIZED = 18 'SnmpStartup failed/not called
Global Const SNMPAPI_MESSAGE_INVALID = 19 'Invalid SNMP message format
Global Const SNMPAPI_HWND_INVALID = 20 'Invalid Window handle
Global Const SNMPAPI_OTHER_ERROR = 99 'For internal/undefined errors
' Generic Transport Layer (TL) Errors
Global Const SNMPAPI_TL_NOT_INITIALIZED = 100 'TL not initialized
Global Const SNMPAPI_TL_NOT_SUPPORTED = 101 'TL does not support protocol
Global Const SNMPAPI_TL_NOT_AVAILABLE = 102 'Network sub-system has failed
Global Const SNMPAPI_TL_RESOURCE_ERROR = 103 'TL resource error
Global Const SNMPAPI_TL_UNDELIVERABLE = 104 'Destination unreachable
Global Const SNMPAPI_TL_SRC_INVALID = 105 'Source endpoint invalid
Global Const SNMPAPI_TL_INVALID_PARAM = 106 'Input parameter invalid
Global Const SNMPAPI_TL_IN_USE = 107 'Source endpoint in use
Global Const SNMPAPI_TL_TIMEOUT = 108 'No response before timeout
Global Const SNMPAPI_TL_PDU_TOO_BIG = 109 'PDU too big for send/receive
Global Const SNMPAPI_TL_OTHER = 199 'Undefined TL error
' v2.0: Structure for SnmpGetVendorInfo() output
Global Const MAXVENDORINFO = 32
Type VENDORINFO
vendorName As String * 64
vendorContact As String * 64
vendorVersionId As String * 32
vendorVersionData As String * 32
vendorEnterprise As Long
End Type
Declare Function SnmpGetTranslateMode Lib "wsnmp32.dll" (nTransMode As Long) As Long
Declare Function SnmpSetTranslateMode Lib "wsnmp32.dll" (ByVal nTransMode As Long) As Long
Declare Function SnmpGetRetransmitMode Lib "wsnmp32.dll" (nRxTxMode As Long) As Long
Declare Function SnmpSetRetransmitMode Lib "wsnmp32.dll" (ByVal nRxTxMode As Long) As Long
Declare Function SnmpGetTimeout Lib "wsnmp32.dll" (ByVal hEntity As Long, nPolicyTO As Long, nActualTO As Long) As Long
Declare Function SnmpSetTimeout Lib "wsnmp32.dll" (ByVal hEntity As Long, ByVal nPolicyTO As Long) As Long
Declare Function SnmpGetRetry Lib "wsnmp32.dll" (ByVal hEntity As Long, nPolicyRetry As Long, nActualRetry As Long) As Long
Declare Function SnmpSetRetry Lib "wsnmp32.dll" (ByVal hEntity As Long, ByVal nPolicyRetry As Long) As Long
' Following Local Database Functions added in v2.0
Declare Function SnmpGetVendorInfo Lib "wsnmp32.dll" (ByRef vendInfo As VENDORINFO) As Long
Declare Function SnmpStartup Lib "wsnmp32.dll" (nVerMaj As Long, nVerMin As Long, nLevel As Long, nTMode As Long, nRMode As Long) As Long
Declare Function SnmpCleanup Lib "wsnmp32.dll" () As Long
Declare Function SnmpOpen Lib "wsnmp32.dll" (ByVal hWnd As Long, ByVal wMsg As Long) As Long
Declare Function SnmpClose Lib "wsnmp32.dll" (ByVal hSession As Long) As Long
Declare Function SnmpSendMsg Lib "wsnmp32.dll" (ByVal hSession As Long, ByVal sEntity As Long, ByVal dEntity As Long, ByVal hContext As Long, ByVal hPDU As Long) As Long
Declare Function SnmpRecvMsg Lib "wsnmp32.dll" (ByVal hSession As Long, sEntity As Long, dEntity As Long, hContext As Long, hPDU As Long) As Long
Declare Function SnmpRegister Lib "wsnmp32.dll" (ByVal hSession As Long, ByVal sEntity As Long, ByVal dEntity As Long, ByVal hContext As Long, smiCOID As OID, ByVal state As Long) As Long
' SnmpRegister() needs to be aliased to SnmpRegisterNull() for "TYPE SAFE"
' usage that will allow registering a NULL notification OID
Declare Function SnmpRegisterNull Lib "wsnmp32.dll" Alias "SnmpRegister" (ByVal hSession As Long, ByVal sEntity As Long, ByVal dEntity As Long, ByVal hContext As Long, ByVal smiCOID As Long, ByVal state As Long) As Long
' Following Communications Functions added in v2.0
Declare Function SnmpCreateSession Lib "wsnmp32.dll" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal fCallBack As Long, ByVal lpClientData As Long) As Long
Declare Function SnmpListen Lib "wsnmp32.dll" (ByVal hEntity As Long, ByVal lStatus As Long) As Long
Declare Function SnmpCancelMsg Lib "wsnmp32.dll" (ByVal hSession As Long, ByVal ReqID As Long) As Long
' Entity/Context FUnctions
Declare Function SnmpStrToEntity Lib "wsnmp32.dll" (ByVal hSession As Long, ByVal Entity As String) As Long
Declare Function SnmpEntityToStr Lib "wsnmp32.dll" (ByVal hEntity As Long, ByVal lenEntity As Long, ByVal strEntity As String) As Long
Declare Function SnmpFreeEntity Lib "wsnmp32.dll" (ByVal hEntity As Long) As Long
Declare Function SnmpStrToContext Lib "wsnmp32.dll" (ByVal hSession As Long, smiOctets As OCTETSTRING) As Long
Declare Function SnmpContextToStr Lib "wsnmp32.dll" (ByVal hContext As Long, smiOctets As OCTET) As Long
Declare Function SnmpFreeContext Lib "wsnmp32.dll" (ByVal hContext As Long) As Long
' Following Entity/Context Functions added in v2.0
Declare Function SnmpSetPort Lib "wsnmp32.dll" (ByVal hEntity As Long, ByVal nPort As Long) As Long
' PDU Functions
Declare Function SnmpCreatePdu Lib "wsnmp32.dll" (ByVal hSession As Long, ByVal typePDU As Long, ByVal ReqID As Long, ByVal errorStat As Long, ByVal errorIdx As Long, ByVal hVBL As Long) As Long
Declare Function SnmpGetPduData Lib "wsnmp32.dll" (ByVal hPDU As Long, typePDU As Long, ReqID As Long, errorStat As Long, errorIdx As Long, hVBL As Long) As Long
Declare Function SnmpSetPduData Lib "wsnmp32.dll" (ByVal hPDU As Long, typePDU As Long, ReqID As Long, errorStat As Long, errorIdx As Long, hVBL As Long) As Long
Declare Function SnmpDuplicatePdu Lib "wsnmp32.dll" (ByVal hSession As Long, ByVal hPDU As Long) As Long
Declare Function SnmpFreePdu Lib "wsnmp32.dll" (ByVal hPDU As Long) As Long
' Variable Binding Functions
Declare Function SnmpCreateVbl Lib "wsnmp32.dll" (ByVal hSession As Long, VarOID As OID, VarVal As Any) As Long
Declare Function SnmpDuplicateVbl Lib "wsnmp32.dll" (ByVal hSession As Long, ByVal hVBL As Long) As Long
Declare Function SnmpFreeVbl Lib "wsnmp32.dll" (ByVal hVBL As Long) As Long
Declare Function SnmpCountVbl Lib "wsnmp32.dll" (ByVal hVBL As Long) As Long
Declare Function SnmpGetVb Lib "wsnmp32.dll" (ByVal hVBL As Long, ByVal Index As Long, VarOID As OID, VarVal As VALUEOCTET) As Long
Declare Function SnmpSetVb Lib "wsnmp32.dll" (ByVal hVBL As Long, ByVal Index As Long, VarOID As OID, VarVal As Any) As Long
Declare Function SnmpDeleteVb Lib "wsnmp32.dll" (ByVal hVBL As Long, ByVal Index As Long) As Long
' SnmpCreateVbl() needs to be aliased to SnmpCreateIntVbl(),
' SnmpCreateOctVbl(), SnmpCreateOidVbl(), SnmpCreateC64Vbl() for "TYPE SAFE" usage
Declare Function SnmpCreateIntVbl Lib "wsnmp32.dll" Alias "SnmpCreateVbl" (ByVal hSession As Long, VarOID As OID, VarVal As VALUEINT) As Long
Declare Function SnmpCreateOctVbl Lib "wsnmp32.dll" Alias "SnmpCreateVbl" (ByVal hSession As Long, VarOID As OID, VarVal As VALUEOCTET) As Long
Declare Function SnmpCreateOidVbl Lib "wsnmp32.dll" Alias "SnmpCreateVbl" (ByVal hSession As Long, VarOID As OID, VarVal As VALUEOID) As Long
Declare Function SnmpCreateC64Vbl Lib "wsnmp32.dll" Alias "SnmpCreateVbl" (ByVal hSession As Long, VarOID As OID, VarVal As VALUECNTR64) As Long
' SnmpSetVb() needs to be aliased to SnmpSetIntVb(), SnmpSetOctVb(),
' SnmpSetOidVb(), SnmpSetC64Vb() for "TYPE SAFE" usage
Declare Function SnmpSetIntVb Lib "wsnmp32.dll" Alias "SnmpSetVb" (ByVal hVBL As Long, ByVal Index As Long, VarOID As OID, VarVal As VALUEINT) As Long
Declare Function SnmpSetOctVb Lib "wsnmp32.dll" Alias "SnmpSetVb" (ByVal hVBL As Long, ByVal Index As Long, VarOID As OID, VarVal As VALUEOCTET) As Long
Declare Function SnmpSetOidVb Lib "wsnmp32.dll" Alias "SnmpSetVb" (ByVal hVBL As Long, ByVal Index As Long, VarOID As OID, VarVal As VALUEOID) As Long
Declare Function SnmpSetC64Vb Lib "wsnmp32.dll" Alias "SnmpSetVb" (ByVal hVBL As Long, ByVal Index As Long, VarOID As OID, VarVal As VALUECNTR64) As Long
' Utility Functions
Declare Function SnmpGetLastError Lib "wsnmp32.dll" (ByVal hSession As Long) As Long
Declare Function SnmpStrToOid Lib "wsnmp32.dll" (ByVal strOID As String, dstOID As OID) As Long
Declare Function SnmpOidToStr Lib "wsnmp32.dll" (srcOID As OID, ByVal size As Long, ByVal strOID As String) As Long
Declare Function SnmpOidCopy Lib "wsnmp32.dll" (srcOID As OID, dstOID As OID) As Long
Declare Function SnmpOidCompare Lib "wsnmp32.dll" (xOID As OID, yOID As OID, ByVal maxLen As Long, Result As Long) As Long
Declare Function SnmpEncodeMsg Lib "wsnmp32.dll" (ByVal hSession As Long, ByVal srcEntity As Long, ByVal dstEntity As Long, ByVal hContext As Long, ByVal hPDU As Long, msgBuff As OCTET) As Long
Declare Function SnmpDecodeMsg Lib "wsnmp32.dll" (ByVal hSession As Long, srcEntity As Long, dstEntity As Long, hContext As Long, hPDU As Long, msgBuff As OCTET) As Long
Declare Function SnmpFreeDescriptor Lib "wsnmp32.dll" (ByVal syntax As Long, Descriptor As Any) As Long
' SnmpFreeDescriptor needs to be Aliased to create SnmpFreeDescOct() &
' SnmpFreeDescOid() for "TYPE SAFE" usage
Declare Function SnmpFreeDescOct Lib "wsnmp32.dll" Alias "SnmpFreeDescriptor" (ByVal syntax As Long, Descriptor As OCTET) As Long
Declare Function SnmpFreeDescOid Lib "wsnmp32.dll" Alias "SnmpFreeDescriptor" (ByVal syntax As Long, Descriptor As OID) As Long
karma:the articles might be helpful to you:
Example: How to Get the Ethernet MAC Address, SNMP Method
http://tangentsoft.net/wskfaq/examples/getmac-snmp.html
Determining a Network Controller MAC Address Using Visual Basic
http://www.mvps.org/vbnet/index.html?code/network/macaddress.htm
Bardo:
以下上Karma(无为)所提供链接的代码,还没有细看与测试,先录上来(以便高手能参考)
Winsock Programmer's FAQ
Example: How to Get the Ethernet MAC Address, SNMP Method
James Marsh writes:
In my search for an ironclad method of finding the MAC address of the ethernet card of a system, I attempted the NetBIOS method as described in the FAQ, but found this to be unacceptable as some of our customers reportedly didn't use [NetBIOS]. I passed over the RPC method, and found a solution in a page maintained by Stas Khirman and Raz Galili.... They describe a method of using the internal SNMP calls in Windows (NT, 95, and 2000 have worked for me) that are used by netstat and other windows utilities, but unfortunately provide no code example for finding the MAC code.
[Below is] a small program I've written up, so that hopefully other people won't have to go through the same learning curve I did with SNMP. I will also attach a file, snmpapi.cpp, that was written by Stas Khirman and distributed on his web page.
A great resource for those interested in retrieving system info through this method is http://www.alvestrand.no/objectid/top.html.
snmpmac.cpp
#include <snmp.h>
#include <conio.h>
#include <stdio.h>
typedef BOOL(WINAPI * pSnmpExtensionInit) (
IN DWORD dwTimeZeroReference,
OUT HANDLE * hPollForTrapEvent,
OUT AsnObjectIdentifier * supportedView);
typedef BOOL(WINAPI * pSnmpExtensionTrap) (
OUT AsnObjectIdentifier * enterprise,
OUT AsnInteger * genericTrap,
OUT AsnInteger * specificTrap,
OUT AsnTimeticks * timeStamp,
OUT RFC1157VarBindList * variableBindings);
typedef BOOL(WINAPI * pSnmpExtensionQuery) (
IN BYTE requestType,
IN OUT RFC1157VarBindList * variableBindings,
OUT AsnInteger * errorStatus,
OUT AsnInteger * errorIndex);
typedef BOOL(WINAPI * pSnmpExtensionInitEx) (
OUT AsnObjectIdentifier * supportedView);
void main()
{
WSADATA WinsockData;
if (WSAStartup(MAKEWORD(2, 0), &WinsockData) != 0) {
fprintf(stderr, "This program requires Winsock 2.x!\n");
return;
}
HINSTANCE m_hInst;
pSnmpExtensionInit m_Init;
pSnmpExtensionInitEx m_InitEx;
pSnmpExtensionQuery m_Query;
pSnmpExtensionTrap m_Trap;
HANDLE PollForTrapEvent;
AsnObjectIdentifier SupportedView;
UINT OID_ifEntryType[] = {
1, 3, 6, 1, 2, 1, 2, 2, 1, 3
};
UINT OID_ifEntryNum[] = {
1, 3, 6, 1, 2, 1, 2, 1
};
UINT OID_ipMACEntAddr[] = {
1, 3, 6, 1, 2, 1, 2, 2, 1, 6
}; //, 1 ,6 };
AsnObjectIdentifier MIB_ifMACEntAddr =
{ sizeof(OID_ipMACEntAddr) / sizeof(UINT), OID_ipMACEntAddr };
AsnObjectIdentifier MIB_ifEntryType = {
sizeof(OID_ifEntryType) / sizeof(UINT), OID_ifEntryType
};
AsnObjectIdentifier MIB_ifEntryNum = {
sizeof(OID_ifEntryNum) / sizeof(UINT), OID_ifEntryNum
};
RFC1157VarBindList varBindList;
RFC1157VarBind varBind[2];
AsnInteger errorStatus;
AsnInteger errorIndex;
AsnObjectIdentifier MIB_NULL = {
0, 0
};
int ret;
int dtmp;
int i = 0, j = 0;
BOOL found = FALSE;
char TempEthernet[13];
m_Init = NULL;
m_InitEx = NULL;
m_Query = NULL;
m_Trap = NULL;
/* Load the SNMP dll and get the addresses of the functions
necessary */
m_hInst = LoadLibrary("inetmib1.dll");
if (m_hInst < (HINSTANCE) HINSTANCE_ERROR) {
m_hInst = NULL;
return;
}
m_Init =
(pSnmpExtensionInit) GetProcAddress(m_hInst, "SnmpExtensionInit");
m_InitEx =
(pSnmpExtensionInitEx) GetProcAddress(m_hInst,
"SnmpExtensionInitEx");
m_Query =
(pSnmpExtensionQuery) GetProcAddress(m_hInst,
"SnmpExtensionQuery");
m_Trap =
(pSnmpExtensionTrap) GetProcAddress(m_hInst, "SnmpExtensionTrap");
m_Init(GetTickCount(), &PollForTrapEvent, &SupportedView);
/* Initialize the variable list to be retrieved by m_Query */
varBindList.list = varBind;
varBind[0].name = MIB_NULL;
varBind[1].name = MIB_NULL;
/* Copy in the OID to find the number of entries in the
Inteface table */
varBindList.len = 1; /* Only retrieving one item */
SNMP_oidcpy(&varBind[0].name, &MIB_ifEntryNum);
ret =
m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus,
&errorIndex);
printf("# of adapters in this system : %i\n",
varBind[0].value.asnValue.number); varBindList.len = 2;
/* Copy in the OID of ifType, the type of interface */
SNMP_oidcpy(&varBind[0].name, &MIB_ifEntryType);
/* Copy in the OID of ifPhysAddress, the address */
SNMP_oidcpy(&varBind[1].name, &MIB_ifMACEntAddr);
do {
/* Submit the query. Responses will be loaded into varBindList.
We can expect this call to succeed a # of times corresponding
to the # of adapters reported to be in the system */
ret =
m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus,
&errorIndex); if (!ret) ret = 1;
else
/* Confirm that the proper type has been returned */
ret =
SNMP_oidncmp(&varBind[0].name, &MIB_ifEntryType,
MIB_ifEntryType.idLength); if (!ret) {
j++;
dtmp = varBind[0].value.asnValue.number;
printf("Interface #%i type : %i\n", j, dtmp);
/* Type 6 describes ethernet interfaces */
if (dtmp == 6) {
/* Confirm that we have an address here */
ret =
SNMP_oidncmp(&varBind[1].name, &MIB_ifMACEntAddr,
MIB_ifMACEntAddr.idLength);
if ((!ret)
&& (varBind[1].value.asnValue.address.stream != NULL)) {
if (
(varBind[1].value.asnValue.address.stream[0] ==
0x44)
&& (varBind[1].value.asnValue.address.stream[1] ==
0x45)
&& (varBind[1].value.asnValue.address.stream[2] ==
0x53)
&& (varBind[1].value.asnValue.address.stream[3] ==
0x54)
&& (varBind[1].value.asnValue.address.stream[4] ==
0x00)) {
/* Ignore all dial-up networking adapters */
printf("Interface #%i is a DUN adapter\n", j);
continue;
}
if (
(varBind[1].value.asnValue.address.stream[0] ==
0x00)
&& (varBind[1].value.asnValue.address.stream[1] ==
0x00)
&& (varBind[1].value.asnValue.address.stream[2] ==
0x00)
&& (varBind[1].value.asnValue.address.stream[3] ==
0x00)
&& (varBind[1].value.asnValue.address.stream[4] ==
0x00)
&& (varBind[1].value.asnValue.address.stream[5] ==
0x00)) {
/* Ignore NULL addresses returned by other network
interfaces */
printf("Interface #%i is a NULL address\n", j);
continue;
}
sprintf(TempEthernet, "%02x%02x%02x%02x%02x%02x",
varBind[1].value.asnValue.address.stream[0],
varBind[1].value.asnValue.address.stream[1],
varBind[1].value.asnValue.address.stream[2],
varBind[1].value.asnValue.address.stream[3],
varBind[1].value.asnValue.address.stream[4],
varBind[1].value.asnValue.address.stream[5]);
printf("MAC Address of interface #%i: %s\n", j,
TempEthernet);}
}
}
} while (!ret); /* Stop only on an error. An error will occur
when we go exhaust the list of interfaces to
be examined */
getch();
/* Free the bindings */
SNMP_FreeVarBind(&varBind[0]);
SNMP_FreeVarBind(&varBind[1]);
}
snmpapi.cpp
/******************************************************************
*
* Copyright (C) Stas Khirman 1998. All rights reserved.
*
* This program is distributed WITHOUT ANY WARRANTY
*
*******************************************************************/
/*************************************************
*
* Reproduction of SNMP.LIB and SNMPAPI.LIB base
* functions
*
* Author: Stas Khirman (staskh@rocketmail.com)
*
*
* Free software: no warranty; use anywhere is ok; spread the
* sources; note any modifications; share variations and
* derivatives (including sending to staskh@rocketmail.com).
*
*
*************************************************/
#include <snmp.h>
SNMPAPI
SNMP_FUNC_TYPE
SnmpUtilOidCpy(
OUT AsnObjectIdentifier *DstObjId,
IN AsnObjectIdentifier *SrcObjId
)
{
DstObjId->ids = (UINT *)GlobalAlloc(GMEM_ZEROINIT,SrcObjId->idLength *
sizeof(UINT));
if(!DstObjId->ids){
SetLastError(1);
return 0;
}
memcpy(DstObjId->ids,SrcObjId->ids,SrcObjId->idLength*sizeof(UINT));
DstObjId->idLength = SrcObjId->idLength;
return 1;
}
VOID
SNMP_FUNC_TYPE
SnmpUtilOidFree(
IN OUT AsnObjectIdentifier *ObjId
)
{
GlobalFree(ObjId->ids);
ObjId->ids = 0;
ObjId->idLength = 0;
}
SNMPAPI
SNMP_FUNC_TYPE
SnmpUtilOidNCmp(
IN AsnObjectIdentifier *ObjIdA,
IN AsnObjectIdentifier *ObjIdB,
IN UINT Len
)
{
UINT CmpLen;
UINT i;
int res;
CmpLen = Len;
if(ObjIdA->idLength < CmpLen)
CmpLen = ObjIdA->idLength;
if(ObjIdB->idLength < CmpLen)
CmpLen = ObjIdB->idLength;
for(i=0;i<CmpLen;i++){
res = ObjIdA->ids[i] - ObjIdB->ids[i];
if(res!=0)
return res;
}
return 0;
}
VOID
SNMP_FUNC_TYPE
SnmpUtilVarBindFree(
IN OUT RFC1157VarBind *VarBind
)
{
BYTE asnType;
// free object name
SnmpUtilOidFree(&VarBind->name);
asnType = VarBind->value.asnType;
if(asnType==ASN_OBJECTIDENTIFIER){
SnmpUtilOidFree(&VarBind->value.asnValue.object);
}
else if(
(asnType==ASN_OCTETSTRING) ||
(asnType==ASN_RFC1155_IPADDRESS) ||
(asnType==ASN_RFC1155_OPAQUE) ||
(asnType==ASN_SEQUENCE)){
if(VarBind->value.asnValue.string.dynamic){
GlobalFree(VarBind->value.asnValue.string.stream);
}
}
VarBind->value.asnType = ASN_NULL;
}
I am afraid I can't help you since I know little about these.
By the way, I agree with the wwwunix.
Maybe you should put a program on the proxy to get the exactly machine IP(MAC) . Or you ask customer run client program which can send the information of this machine IP(MAC) to server before they access data on server each time.
*****************************************************
请问:如何实现网卡的物理地址和IP地址的相互查询 (即在局域网内,知道IP查MAC地址,知道MAC地址查IP)
你可以使用arp程序(WINDOWS自带)
eg: arp -a 192.168.0.1
如果使用程序查的话,你需要去实现一个ARP、RARP协议的软件
如果只是查看一下对应关系,可以登陆到以太网交换机上查看IP和MAC之间的对应
在Windows9x中,可按如下思路进行:
1、建立局域网内IP地址--MAC地址对照表:
调用icmp.dll中的IcmpSendEcho函数对一个地址发一个ping操作。
成功后马上调用Iphlpapi.dll中的GetIpNetTable函数来取所有的ARP表,从中找出
所关心的MAC地址。
保存IP地址和MAC地址。
依此类推,取得局域网内所有IP地址和MAC地址的对照表。
(可取范围为IPADDR and SUBMASK 子网范围内的对照表)
2、做一个查询界面。
Windows2000中,应该可以更简单一些。因为它支持更多的函数如SendARP。
IP to MAC 较容易:
方法1. DOS命令: nbtstat -a IP
方法2. DOS命令: ping IP 然后 arp -a
方法3. 仿照nbtstat,向对方的137端口发数据包,包的内容如下(C代码)
BYTE b[50]={0x0,0x00,0x0,0x10,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,
0x20,0x43,0x4b,0x41,0x41,0x41,0x41,0x41,0x41,0x41,
0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,
0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,
0x41,0x41,0x41,0x0,0x0,0x21,0x0,0x1};
(这是发nbtstat命令后用IPMan截获的),对方会向你返回一个数据包,
其中有对方的工作组,主机名,用户名,MAC地址。当然,返回包的格式要
自己分析,也可以查RFC文档。你自己的端口可以随便取一个值。
方法4.在win9x下可用IPMan直接发ARP。
方法5.在win2000下可用SendArp()直接发ARP。
----------------------------------------------------------------
MAC to IP似乎较困难。
Win9x下IPMan有此项功能,但我试了一下似乎不行。
来自:zw84611, 时间:2001-10-7 19:37:00, ID:659172
发出去了,是用VC写的。因为我不喜欢Delphi5 的udp控件。其实用delphi也一样。很
简单的,就是向对方137端口发内容为
BYTE b[50]={0x0,0x00,0x0,0x10,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,
0x20,0x43,0x4b,0x41,0x41,0x41,0x41,0x41,0x41,0x41,
0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,
0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,
0x41,0x41,0x41,0x0,0x0,0x21,0x0,0x1};
的UDP包(Delphi中用$代替0x),对方就会给你应答,你接收就是了。
Delphi源码如下,其中UDP用Socket API实现。
-------------------------------------------------------
unit udp;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, winsock,
StdCtrls;
const
WM_SOCK = WM_USER + 1; //自定义windows消息
UDPPORT = 6767; //设定UDP端口号
NBTPORT = 137;
type
Tfrmmain = class(TForm)
Button1: TButton;
ListBox1: TListBox;
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
s: TSocket;
addr: TSockAddr;
FSockAddrIn : TSockAddrIn; //利用消息实时获知UDP消息
procedure ReadData(var Message: TMessage); message WM_SOCK;
public
{ Public declarations }
procedure SendData(b:array of byte);
end;
var
frmmain: Tfrmmain;
implementation
{$R *.DFM}
procedure Tfrmmain.FormCreate(Sender: TObject);
var
TempWSAData: TWSAData;
//optval: integer;
begin
// 初始化SOCKET
if WSAStartup($101, TempWSAData)=1 then
showmessage('StartUp Error!');
s := Socket(AF_INET, SOCK_DGRAM, 0);
if (s = INVALID_SOCKET) then //Socket创建失败
begin
showmessage(inttostr(WSAGetLastError())+' Socket创建失败');
CloseSocket(s);
end;
//本机SockAddr绑定
addr.sin_family := AF_INET;
addr.sin_addr.S_addr := INADDR_ANY;
addr.sin_port := htons(UDPPORT);
if Bind(s, addr, sizeof(addr)) <> 0 then
begin
showmessage('bind fail');
end;
WSAAsyncSelect(s, frmmain.Handle , WM_SOCK, FD_READ);
//对方SockAddrIn设定
FSockAddrIn.SIn_Family := AF_INET;
FSockAddrIn.SIn_Port := htons(NBTPORT);
end;
procedure Tfrmmain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
CloseSocket(s);
end;
procedure GetInfo(buf: Array of byte);
{这个过程是根据返回报文的内容凑出来的,偶尔会出错。如果能根据
报文格式的定义来做(可查阅相关RFC文档,可惜我没时间,以后做吧),就更好了。
如果你作出来了,不妨寄给我一个哟。e-mail:zw84611@sina.com}
var bAdd,bMac:boolean;
str,strHost,strHex,strMac:string;
tem,i,j:integer;
begin
bAdd:=true;
strHost:='';
strHex:='';
tem:=0;
for i:=57 to 500 do //57-72
begin
if(Buf[i]=$cc)then break;
if(Buf[i]=$20)then bAdd:=false;
if(bAdd)then
begin
str:=char(Buf[i]);
strHost:=strHost+str;
str:=Format('%x.',[Buf[i]]);
strHex:=strHex+str;
end;
inc(tem);
if(tem mod 18=0)then
begin
bAdd:=true;
Trim(strHex);
bMac:=true;
for j:=1 to length(strHex) do if strHex[j]>'0' then bMac:=false;
//showmessage(strHex);
if(bMac)then
with frmmain.ListBox1 do
begin
Items.Delete(items.count-1);
Items.add('mac address:');
Delete(strMac,17,length(strMac)-17);
Items.Add(strMac);
break;
end;
frmmain.ListBox1.items.Add(strHost);
strMac:=strHex;
strHost:='';
strHex:='';
end;
end;
end;
procedure Tfrmmain.ReadData(var Message: TMessage);
var
buffer: Array [1..500] of byte;
len{,i}: integer;
flen: integer;
Event: word;
value: string;
begin
value:='';
Event := WSAGetSelectEvent(Message.LParam);
if Event = FD_READ then
begin
len := recvfrom(s, buffer, sizeof(buffer), 0, FSockAddrIn, flen);
{for i:=1 to len do value:=value+format('%x',[buffer[i]]);
ListBox1.items.add(value);
value:='';
for i:=1 to len do if char(buffer[i])<>#0 then value:=value+char(buffer[i]);
ListBox1.items.add(value);}
if len<> 0 then GetInfo(buffer);
end;
end;
procedure Tfrmmain.SendData(b:array of byte);
var
len: integer;
begin
FSockAddrIn.SIn_Addr.S_addr := inet_addr(pchar(edit1.text));
len := sendto(s, b[0],50, 0, FSockAddrIn, sizeof(FSockAddrIn));
//if (WSAGetLastError() <> WSAEWOULDBLOCK) and (WSAGetLastError() <> 0) then showmessage(inttostr(WSAGetLastError()));
if len = SOCKET_ERROR then
showmessage('send fail');
if len <> 50 then
showmessage('Not Send all');
end;
procedure Tfrmmain.Button1Click(Sender: TObject);
const NbtstatPacket:array[0..49]of byte
=($0,$0,$0,$10,$0,$1,
$0,$0,$0,$0,$0,$0,$20,$43,$4b,
$41,$41,$41,$41,$41,$41,$41,$41,
$41,$41,$41,$41,$41,$41,$41,$41,
$41,$41,$41,$41,$41,$41,$41,$41,
$41,$41,$41,$41,$41,$41,$0,$0,$21,$0,$1);
begin
senddata(NbtstatPacket);
end;
end.