第三种方法- 使用SNMP扩展API 我要讨论的第三种方法是使用Windows的SNMP(简单网络管理协议)扩展来取得MAC地址。在我的经验里,这个协议很简单。代码也是直勾勾的向前的。基本步骤和Netbios相同: 1》取得网卡列表 2》查询每块卡的类型和MAC地址 3》保存当前网卡 我个人对SNMP了解不多,但如我刚刚所言,代码十分清楚。
snmp.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() { 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}; 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;
/* 载入SNMP DLL并取得实例句柄 */ 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);
/* 初始化用来接收m_Query查询结果的变量列表 */ varBindList.list = varBind; varBind[0].name = MIB_NULL; varBind[1].name = MIB_NULL;
/* 在OID中拷贝并查找接口表中的入口数量 */ 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 : %in", varBind[0].value.asnValue.number); varBindList.len = 2;
/* 拷贝OID的ifType-接口类型 */ SNMP_oidcpy(&varBind[0].name, &MIB_ifEntryType);
/* 拷贝OID的ifPhysAddress-物理地址 */ SNMP_oidcpy(&varBind[1].name, &MIB_ifMACEntAddr);
do {
/* 提交查询,结果将载入 varBindList。 可以预料这个循环调用的次数和系统中的接口卡数量相等 */ ret = m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus, &errorIndex); if (!ret) ret = 1; else /* 确认正确的返回类型 */ ret = SNMP_oidncmp(&varBind[0].name, &MIB_ifEntryType, MIB_ifEntryType.idLength); if (!ret) { j++; dtmp = varBind[0].value.asnValue.number; printf("Interface #%i type : %in", j, dtmp);
/* Type 6 describes ethernet interfaces */ if (dtmp == 6) {
/* 确认我们已经在此取得地址 */ 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)) { /* 忽略所有的拨号网络接口卡 */ printf("Interface #%i is a DUN adaptern", 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)) { /* 忽略由其他的网络接口卡返回的NULL地址 */ printf("Interface #%i is a NULL addressn", 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: %sn", j, TempEthernet);} } } } while (!ret); /* 发生错误终止。 */ getch();
FreeLibrary(m_hInst); /* 解除绑定 */ SNMP_FreeVarBind(&varBind[0]); SNMP_FreeVarBind(&varBind[1]); }

|