您的位置:首页 > 其它

MFC:使用SNMP编辑(添加/删除/修改)ARP表

2012-03-15 08:40 369 查看
MFC:使用SNMP编辑(添加/删除/修改)ARP表

本文章永久地址 http://www.limou.net/?p=306
介绍

这个工具像Windows命令行工具arp.exe一样显示和修改IP/物理地址转表(ARP表)。该工具将做两件事情。

显示ARP表

添加、删除、修改ARP表

这两项工作通过SNMP(简单网络管理协议)扩展库来完成。

通过SNMP处理IP和MAC地址

你可以通过SNMP读取或修改ARP表,通过SNMP得到或设置对象信息。SNMP命令的请求与响应是依靠MIB(管理信息库)来完成的。MIB为树装结构,MIB拥有所有为我们所用的可管理对象。

下面是MIB ipNetToMediaEntry条目

ipNetToMediaEntry OBJECT-TYPE

SYNTAX IpNetToMediaEntry

ACCESS not-accessible

STATUS mandatory

DESCRIPTION

"Each entry contains one IpAddress to 'physical'

address equivalence."

INDEX { ipNetToMediaIfIndex,

ipNetToMediaNetAddress }

::= { ipNetToMediaTable 1 }

MIB通过OID(对象标识)数字来存取对象,每个对象拥有一个数字,子对象拥有父对象的数字和自己的数字,数字之间用”.”来分割。例如:父对象数字为”1″,子对象数字为”3″,则子对象OID为”1.3″,子对象的子对象可以是”1.3.6″,…”1.3.6.1.2.1″等等…

下面是对象树的简单框图:



类的初始化

我们使用SnmpExtensionQuery函数来发送SNMP请求,使用之前我们必须调用SnmpExtensionInit来初始化SNMP扩展代理DLL。

这两个函数包含于Microsoft的inetmib1.dll中。

因此我们在类的构造函数中加载动态库并得到函数的地址,然后调用SnmpExtensionInit初始化SNMP扩展代理DLL。

下面是CARP类的构造函数

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

CARP::CARP()

{

// Load dynamic library: inetmib1.dll

hMIBLibrary = LoadLibrary(TEXT("inetmib1.dll"));

// If library loaded, get addresses of (SnmpExtensionInit, pfnSnmpExtensionQuery) functions

if (hMIBLibrary)

{

pfnSnmpExtensionInit = (PFNSNMPEXTENSIONINIT) GetProcAddress(hMIBLibrary, "SnmpExtensionInit");

pfnSnmpExtensionQuery = (PFNSNMPEXTENSIONQUERY) GetProcAddress(hMIBLibrary, "SnmpExtensionQuery");

// If success get addresses and initialize SNMP, bInitialized = true

if (pfnSnmpExtensionInit && pfnSnmpExtensionQuery)

{

HANDLE hPollForTrapEvent;

AsnObjectIdentifier aoiSupportedView;

bInitialized = pfnSnmpExtensionInit(0, &hPollForTrapEvent, &aoiSupportedView);

}

}

else

{

// If fail to get addresses, bInitialized = false

bInitialized = FALSE;

AfxMessageBox(_T("Load library fail"));

}

}

得到ARP条目

函数GetEntries类似arp.exe -a,可以得到ARP条目,函数有三个参数:

PTable指针指向arpTable结构数组,用于填充IP和MAC地址。

TableLength是数组长度

AdapterIndex是NIC适配器的编号。

使用3个OID来得到ARP表条目:OID[0] = “1.3.6.1.2.1.4.22.1.1″ ,得到接口索引号。然后和OID[1] = “1.3.6.1.2.1.4.22.1.2″比较,得到IP和MAC地址OID[2] = “1.3.6.1.2.1.4.22.1.4″, 得到条目类型(静态或动态)

//-----------------------------------------------------------------------

// Function: GetEntries: Read ARP table for specific NIC interface.

//

// Parameters:

// pTable Pointer to array of arpTable struct

// TableLength Length of the array

// AdapterIndex NIC Adapter index number

//

// Returns:

// Number of read ARP entries

//-----------------------------------------------------------------------

int CARP::GetEntries(arpTable* pTable, int TableLength, int AdapterIndex)

{

// Be sure initialize SNMP true

if (!bInitialized)

return 0;

SnmpVarBindList SVBList[3];

SnmpVarBind SVBVars[3];

UINT OID[3][10];

AsnInteger32 aiErrorStatus[3], aiErrorIndex[3];

AsnObjectIdentifier AsnOID0 = {sizeof(OID[0])/sizeof(UINT), OID[0]};

AsnObjectIdentifier AsnOID1 = {sizeof(OID[1])/sizeof(UINT), OID[1]};

AsnObjectIdentifier AsnOID2 = {sizeof(OID[2])/sizeof(UINT), OID[2]};

unsigned long pIPAddress;

unsigned long pMACAddress;

int iEntries;

//-----------------------------------------------------------------------

// Fill array of 3 OIDs

//

// OID[0] : "1.3.6.1.2.1.4.22.1.1", ipNetToMediaIfIndex

// The interface on which this entry's equivalence is effective

//

// OID[1] : "1.3.6.1.2.1.4.22.1.2", ipNetToMediaPhysAddress

// The media-dependent 'physical' address

//

// OID[2] : "1.3.6.1.2.1.4.22.1.4", ipNetToMediaType

// Entry type: 1:Other, 2:Invalid(Remove), 3:Dynamic, 4:Static

//

for (int count=0; count<3; count++)

{

OID[count][0] = 1;

OID[count][1] = 3;

OID[count][2] = 6;

OID[count][3] = 1;

OID[count][4] = 2;

OID[count][5] = 1;

OID[count][6] = 4;

OID[count][7] = 22;

OID[count][8] = 1;

switch(count)

{

case 0:

// Adapter interface

OID[count][9] = 1;

break;

case 1:

// MAC address

OID[count][9] = 2;

break;

case 2:

// Entry Type

OID[count][9] = 4;

break;

}

}

ZeroMemory(pTable, sizeof(arpTable)*TableLength);

SVBList[0].len = 1;

SVBList[0].list = &SVBVars[0];

SnmpUtilOidCpy(&SVBVars[0].name, &AsnOID0);

SVBList[1].len = 1;

SVBList[1].list = &SVBVars[1];

SnmpUtilOidCpy(&SVBVars[1].name, &AsnOID1);

SVBList[2].len = 1;

SVBList[2].list = &SVBVars[2];

SnmpUtilOidCpy(&SVBVars[2].name, &AsnOID2);

iEntries = 0;

do

{

aiErrorStatus[0] = 0;

aiErrorIndex[0] = 0;

aiErrorStatus[1] = 0;

aiErrorIndex[1] = 0;

aiErrorStatus[2] = 0;

aiErrorIndex[2] = 0;

// Query information of 3 OIDs

if (pfnSnmpExtensionQuery(SNMP_PDU_GETNEXT, &SVBList[0], &aiErrorStatus[0], &aiErrorIndex[0]))

if (pfnSnmpExtensionQuery(SNMP_PDU_GETNEXT, &SVBList[1], &aiErrorStatus[1], &aiErrorIndex[1]))

if (pfnSnmpExtensionQuery(SNMP_PDU_GETNEXT, &SVBList[2], &aiErrorStatus[2], &aiErrorIndex[2]))

if (aiErrorStatus[0] == SNMP_ERRORSTATUS_NOERROR &&

aiErrorStatus[1] == SNMP_ERRORSTATUS_NOERROR &&

aiErrorStatus[2] == SNMP_ERRORSTATUS_NOERROR) // Check for error

{

//-----------------------------------------------------------------------

// From MSDN Help: http://msdn2.microsoft.com/en-us/library/aa378021.aspx
//

// If the extension agent cannot resolve the variable bindings on a Get Next request,

// it must change the name field of the SnmpVarBind structure to the value of the object

// identifier immediately following that of the currently supported MIB subtree view.

// For example, if the extension agent supports view ".1.3.6.1.4.1.77.1", a Get Next

// request on ".1.3.6.1.4.1.77.1.5.1" would result in a modified name field of ".1.3.6.1.4.1.77.2".

// This signals the SNMP service to continue the attempt to resolve the variable bindings

// with other extension agents

//-----------------------------------------------------------------------

if(SnmpUtilOidNCmp(&SVBVars[0].name, &AsnOID0, AsnOID0.idLength))

break;

if(SnmpUtilOidNCmp(&SVBVars[1].name, &AsnOID1, AsnOID1.idLength))

break;

if(SnmpUtilOidNCmp(&SVBVars[2].name, &AsnOID2, AsnOID2.idLength))

break;

// Verify selected Adapter interface

if (AdapterIndex == SVBList[0].list->value.asnValue.number)

{

// pIPAddress get pointer ro IP Address

pIPAddress = (unsigned long)SVBList[1].list->name.ids;

pTable[iEntries].IPAddress[0] = *(unsigned char *)(pIPAddress + 44);

pTable[iEntries].IPAddress[1] = *(unsigned char *)(pIPAddress + 48);

pTable[iEntries].IPAddress[2] = *(unsigned char *)(pIPAddress + 52);

pTable[iEntries].IPAddress[3] = *(unsigned char *)(pIPAddress + 56);

// pIPAddress get pointer ro MAC Address

pMACAddress = (unsigned long)SVBList[1].list->value.asnValue.string.stream;

if (pMACAddress)

{

pTable[iEntries].MACAddress[0] = *(unsigned char *)(pMACAddress + 0);

pTable[iEntries].MACAddress[1] = *(unsigned char *)(pMACAddress + 1);

pTable[iEntries].MACAddress[2] = *(unsigned char *)(pMACAddress + 2);

pTable[iEntries].MACAddress[3] = *(unsigned char *)(pMACAddress + 3);

pTable[iEntries].MACAddress[4] = *(unsigned char *)(pMACAddress + 4);

pTable[iEntries].MACAddress[5] = *(unsigned char *)(pMACAddress + 5);

}

// Entry Type

pTable[iEntries].Type = (unsigned long)SVBList[2].list->value.asnValue.number;

// Type must be one of (1, 2, 3, 4)

if (pTable[iEntries].Type>=1 && pTable[iEntries].Type<=4)

iEntries++; // Move to next array position

}

}

else

break; // If error exit do-while

}

while(iEntries < TableLength);

// Frees the memory allocated for the specified object identifiers

SnmpUtilOidFree(&SVBVars[2].name);

SnmpUtilOidFree(&SVBVars[1].name);

SnmpUtilOidFree(&SVBVars[0].name);

return iEntries; // Return number of Entries

}

编辑ARP表条目

EditEntry函数可以添加、修改、删除ARP条目:

添加动态条目,就像:arp.exe 1.2.3.4 11-22-33-44-55-66

添加静态条目,就像:arp.exe –s 1.2.3.4 11-22-33-44-55-66

删除条目,就像:arp.exe –d 1.2.3.4

添加新条目,如果IP地址在ARP表中不存在则添加进去,如果已经存在则被更新。

删除条目,只需要提供NIC接口中的IP地址,MAC地址不需要提供。

函数有四个参数:4字节的IPAddress,6字节的MACAddress,条目类型(2:删除,3:动态,4:静态)

AdapterIndex:NIC适配器编号

使用4个OID设置ARP表条目:

OID[0] = “1.3.6.1.2.1.4.22.1.1″, 设置接口编号

OID[1] = “1.3.6.1.2.1.4.22.1.2″, 设置MAC地址

OID[3] = “1.3.6.1.2.1.4.22.1.3″, 设置IP地址

OID[2] = “1.3.6.1.2.1.4.22.1.4″, 设置条目类型 (静态或动态), 或删除

//-----------------------------------------------------------------------

// Function: EditEntry: Add/Modify/Remove ARP entry for specific NIC interface.

//

// Parameters:

// IPAddress Array of 4 BYTES, 4 octs of IP Address

// MACAddress Array of 4 BYTES, 6 octs of MAC Address

// Type Entry type (2:Remove, 3:Dynamic, 4:Static)

// AdapterIndex NIC Adapter index number

//

// Returns:

// TRUE if set successfully, FALSE otherwise.

//-----------------------------------------------------------------------

BOOL CARP::EditEntry(unsigned char IPAddress[4], unsigned char MACAddress[6], unsigned long Type, int AdapterIndex)

{

if (!bInitialized)

return 0;

SnmpVarBindList SVBList;

SnmpVarBind SVBVars[4];

UINT OID[4][10];

AsnInteger32 aiErrorStatus, aiErrorIndex;

BOOL bReturn = FALSE;

//-----------------------------------------------------------------------

// Fill array of 4 OIDs

//

// OID[0] : "1.3.6.1.2.1.4.22.1.1", ipNetToMediaIfIndex

// The interface on which this entry's equivalence is effective

//

// OID[1] : "1.3.6.1.2.1.4.22.1.2", ipNetToMediaPhysAddress

// The media-dependent 'physical' address

//

// OID[2] : "1.3.6.1.2.1.4.22.1.3", ipNetToMediaNetAddress

// The IpAddress corresponding to the media-dependent 'physical' address

//

// OID[3] : "1.3.6.1.2.1.4.22.1.4", ipNetToMediaType

// Entry type: 1:Other, 2:Invalid(Remove), 3:Dynamic, 4:Static

//-----------------------------------------------------------------------

for (int count=0; count<4; count++)

{

OID[count][0] = 1;

OID[count][1] = 3;

OID[count][2] = 6;

OID[count][3] = 1;

OID[count][4] = 2;

OID[count][5] = 1;

OID[count][6] = 4;

OID[count][7] = 22;

OID[count][8] = 1;

OID[count][9] = 1 + count;

switch(count)

{

case 0:

// OID[0] : "1.3.6.1.2.1.4.22.1.1", ipNetToMediaIfIndex

// The interface on which this entry's equivalence is effective

SVBVars[count].value.asnType = ASN_INTEGER;

SVBVars[count].value.asnValue.number = AdapterIndex;

break;

case 1:

// OID[1] : "1.3.6.1.2.1.4.22.1.2", ipNetToMediaPhysAddress

// The media-dependent 'physical' address

SVBVars[count].value.asnType = ASN_OCTETSTRING;

SVBVars[count].value.asnValue.string.stream = MACAddress;

SVBVars[count].value.asnValue.string.length = 6; // MAC Address length

SVBVars[count].value.asnValue.string.dynamic= FALSE;

break;

case 2:

// OID[2] : "1.3.6.1.2.1.4.22.1.3", ipNetToMediaNetAddress

// The IpAddress corresponding to the media-dependent 'physical' address

SVBVars[count].value.asnType = ASN_IPADDRESS;

SVBVars[count].value.asnValue.string.stream = IPAddress;

SVBVars[count].value.asnValue.string.length = 4; // IP Address length

SVBVars[count].value.asnValue.string.dynamic= FALSE;

break;

case 3:

// OID[3] : "1.3.6.1.2.1.4.22.1.4", ipNetToMediaType

// Entry type: 2:Remove, 3:Dynamic, 4:Static

SVBVars[count].value.asnType = ASN_INTEGER;

SVBVars[count].value.asnValue.number = Type;

break;

}

AsnObjectIdentifier AsnOID = {sizeof(OID[count])/sizeof(UINT), OID[count]};

SnmpUtilOidCpy(&SVBVars[count].name, &AsnOID);

}

SVBList.len = 4;

SVBList.list = SVBVars;

aiErrorStatus = 0;

aiErrorIndex = 0;

// Set information of entry (4 OIDs)

if (pfnSnmpExtensionQuery(SNMP_PDU_SET, &SVBList, &aiErrorStatus, &aiErrorIndex))

if (aiErrorStatus == SNMP_ERRORSTATUS_NOERROR)

bReturn = TRUE; // If success set bReturn = true

// Frees the memory allocated for the specified object identifiers

SnmpUtilOidFree(&SVBVars[3].name);

SnmpUtilOidFree(&SVBVars[2].name);

SnmpUtilOidFree(&SVBVars[1].name);

SnmpUtilOidFree(&SVBVars[0].name);

return bReturn; // TRUE if set successfully, FALSE otherwise.

}

请继续关注 李木空间 www.limou.net 更多精彩源代码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐