分享一段SNMP的代码,顺带列出几个不解之处

ynwlgh 2011-02-18 05:07:36
codeproject上来的代码,用于获取ARP列表



// Function: GetEntries: Read ARP table for specific NIC interface.
//第一,二个参数用于获取数据
int GetEntries(arpTable* pTable, int tableLen, int adapterIndex)
{
UINT OID[3][10];

//三个OID。
for(int i=0;i<3;i++)
{
OID[i][0] = 1;
OID[i][1] = 3;
OID[i][2] = 6;
OID[i][3] = 1;
OID[i][4] = 2;
OID[i][5] = 1;
OID[i][6] = 4;
OID[i][7] = 22;
OID[i][8] = 1;

switch(i)
{
case 0:
// Adapter interface
OID[i][9] = 1;
break;

case 1:
// MAC address
OID[i][9] = 2;
break;

case 2:
// Entry Type
OID[i][9] = 4;
break;
}
}

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


SnmpVarBindList SVBList[3];
SnmpVarBind SVBVars[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]};

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);

int iEntries=0;
AsnInteger32 aiErrorStatus[3], aiErrorIndex[3];

do
{
aiErrorStatus[0]=0;
aiErrorIndex[0]=0;
aiErrorStatus[1]=0;
aiErrorIndex[1]=0;
aiErrorStatus[2]=0;
aiErrorIndex[2]=0;

//SnmpExtensionQuery的函数指针
if(!pfunSnmpExtensionQuery(SNMP_PDU_GETNEXT,&SVBList[0],&aiErrorStatus[0],&aiErrorIndex[0]))
continue; //@@@@@@@ 1
if(!pfunSnmpExtensionQuery(SNMP_PDU_GETNEXT,&SVBList[1],&aiErrorStatus[1],&aiErrorIndex[1]))
continue;
if(!pfunSnmpExtensionQuery(SNMP_PDU_GETNEXT,&SVBList[2],&aiErrorStatus[2],&aiErrorIndex[2]))
continue;

if(aiErrorStatus[0]!=SNMP_ERRORSTATUS_NOERROR
||aiErrorStatus[1]!=SNMP_ERRORSTATUS_NOERROR
||aiErrorStatus[2]!=SNMP_ERRORSTATUS_NOERROR)
break;

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;


if(SVBList[0].list->value.asnValue.number==adapterIndex)
{
unsigned long pIPAddress;
unsigned long pMACAddress;

//获得ARP IP
pIPAddress=(unsigned long)SVBList[1].list->name.ids;

pTable[iEntries].IPAddress[0]=*(unsigned char*)(pIPAddress+44); //@@@@@@@@@@@@@ 2
pTable[iEntries].IPAddress[1]=*(unsigned char*)(pIPAddress+48);
pTable[iEntries].IPAddress[2]=*(unsigned char*)(pIPAddress+52);
pTable[iEntries].IPAddress[3]=*(unsigned char*)(pIPAddress+56);

//获得MAC
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);
}


// 获得ARP类型,动态/静态。。
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

}

} while (iEntries<tableLen);

//清理工作
// 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
}
...全文
196 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
ynwlgh 2011-02-23
  • 打赏
  • 举报
回复
算了,改用snmp++了。简单方便些
oyljerry 2011-02-18
  • 打赏
  • 举报
回复
SNMP_PDU_GETNEXT 应该是获取下一个数据,遍历

MIB是SNMP协议中的数据结构,标示OID是数据标示符,参考SNMP协议RFC
ynwlgh 2011-02-18
  • 打赏
  • 举报
回复
哦。SNMP_PDU_GETNEXT用于在do while循环中获取吧。
CSDN API文档:
注解:
当SNMP服务接收一个SNMP PDU请求时,它调用SnmpExtensionQuery函数来处理此请求。扩展代理必须遵循RFC1157中的规则来解析变量绑定或者产生一个错误。
如果扩展代理不能解析取下一个(Get Next)请求时的变量绑定,它就必须改变SnmpVarBind结构的name域的值为沿当前支持的MIB子树图的紧下面一个对象标识符的值。例如,如果扩展代理支持图”.1.3.6.1.4.77.1”, 对于”.1.3.6.1.4.1.77.1.5.1”的取下一个(Get Next)请求将导致改变的name域".1.3.6.1.4.1.77.2"。此向SNMP会话发信号以继续试图解析与其它扩展代理的变量绑定。
特别注意在调用SnmpExtensionQuery函数的过程中SNMP服务和扩展代理或许需要交换动态分配的内存。服务在每一传递到扩展代理的SnmpVarBind结构中动态分配对象标识符。然而,当扩展代理处理取下一个(Get Next)请求时为了替换此对象标识符它必须释放这个内存。扩展代理为变长对象类型分配动态内存。SNMP服务把此对象置于应答PDU中后释放这个内存。
ynwlgh 2011-02-18
  • 打赏
  • 举报
回复
1.SnmpExtensionQuery这个函数用来干嘛,没太看清楚。
他用SNMP_PDU_GETNEXT这个参数是干嘛?
获取值的话,为什么不用 SNMP_PDU_GET。

2.pTable[iEntries].IPAddress[0]=*(unsigned char*)(pIPAddress+44); //@@@@@@@@@@@@@ 2
这里为什么加上44?

3.MIB的结构到底是怎么个样。
好像没有相关的文档说明,OID对应的值该怎么有效获得。
用这个函数SnmpExtensionQuery的话,数据是保存在AsnObjectName(即AsnAny),或AsnObjectSyntax里边。
这结构太太复杂。

暂时只有这么多。
资源下载链接为: https://pan.quark.cn/s/abbae039bf2a 在计算机科学领域,编译原理是研究如何将编程语言转化为机器可执行代码的理论基础。其中,三地址代码(Three-Address Code,TAC)作为一种中间表示形式,在编译器设计中经常被使用,尤其是在生成目标代码的阶段。本文将深入探讨三地址代码的概念、生成器的工作原理及其在编译过程中的作用。 三地址代码是一种简单的低级抽象语法树(AST)表示,每条指令涉及三个操作数,通常包括两个源操作数和一个目的操作数。这种格式简化了代码优化和目标代码生成的复杂性。例如,一个简单的算术表达式“x = y + z”在三地址代码中可能表示为: 在这个例子中,“t1”是一个临时变量,存储了“y + z”的结果,然后这个结果被赋值给“x”。 生成三地址代码的过程通常发生在编译器的中间阶段,即语法分析之后,语义分析之前。这个阶段称为“代码生成”或“中间代码生成”。编译器通过词法分析器处理源代码,将其转化为标记流;接着,语法分析器根据上下文无关文法将标记流解析成抽象语法树。三地址代码生成器就是在这个阶段介入,它遍历AST,为每个节点生成对应的三地址指令。 在Turbo C3.0这样的编译器环境下,开发者可以实现自己的三地址代码生成器。虽然Turbo C3.0是一款较老的编译器,但其C语言编译器设计原理依然适用于现代编译器开发。开发过程中,我们需要考虑如下关键点: 符号表管理:符号表记录了程序中所有标识符的类型、作用域和关联地址,对于生成三地址代码至关重要,因为它提供了关于操作数的类型信息。 数据类型转换:编译器必须处理不同数据类型的运算,确保它们在三地址代码中正确表示。例如,整型与浮点型之间的转换需要特别处理。

18,363

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧