资源描述
以太网络拓扑发现
一. 原理概述
简单网络管理协议(SNMP)首先是由Internet工程任务组织(Internet Engineering Task Force)(IETF)的研究小组为了解决Internet上的路由器管理问题而提出的。许多人认为 SNMP在IP上运行的原因是Internet运行的是TCP/IP协议,然而事实并不是这样。
SNMP被设计成与协议无关,所以它可以在IP,IPX,AppleTalk,OSI以及其他用到的传输协议上被使用。
SNMP是一系列协议组和规范(见下表),它们提供了一种从网络上的设备中收集网络管理信息的方法。SNMP也为设备向网络管理工作站报告问题和错误提供了一种方法。
名字
说明
MIB
管理信息库
SMI
管理信息的结构和标识
SNMP
简单网络管理协议
从被管理设备中收集数据有两种方法:一种是只轮询(polling-only)的方法,另一种是基于中断(interrupt-based)的方法。
如果你只使用只轮询的方法,那么网络管理工作站总是在控制之下。而这种方法的缺陷在于信息的实时性,尤其是错误的实时性。你多久轮询一次,并且在轮询时按照什么样的设备顺序呢?如果轮询间隔太小,那么将产生太多不必要的通信量。如果轮询间隔太大,并且在轮询时顺序不对,那么关于一些大的灾难性的事件的通知又会太馒。这就违背了积极主动的网络管理目的。
当有异常事件发生时,基于中断的方法可以立即通知网络管理工作站(在这里假设该设备还没有崩溃,并且在被管理设备和管理工作站之间仍有一条可用的通信途径)。然而,这种方法也不是没有他的缺陷的,首先,产生错误或自陷需要系统资源。如果自陷必须转发大量的信息,那么被管理设备可能不得不消耗更多的时间和系统资源来产生自陷,从而影响了它执行主要的功能(违背了网络管理的原则2)。
而且,如果几个同类型的自陷事件接连发生,那么大量网络带宽可能将被相同的信息所占用(违背了网络管理的原则1)。尤其是如果自陷是关于网络拥挤问题的时候,事情就会变得特别糟糕。克服这一缺陷的一种方法就是对于被管理设备来说,应当设置关于什么时候报告问题的阈值(threshold)。但不幸的是这种方法可能再一次违背了网络管理的原则2,因为设备必须消耗更多的时间和系统资源,来决定一个自陷是否应该被产生。
结果,以上两种方法的结合:面向自陷的轮询方法(trap-directed polling)可能是执行网络管理最为有效的方法了。一般来说,网络管理工作站轮询在被管理设备中的代理来收集数据,并且在控制台上用数字或图形的表示方式来显示这些数据。这就允许网络管理员分析和管理设备以及网络通信量了。
被管理设备中的代理可以在任何时候向网络管理工作站报告错误情况,例如预制定阈值越界程度等等。代理并不需要等到管理工作站为获得这些错误情况而轮询他的时候才会报告。这些错误情况就是众所周知的SNMP自陷(trap)。
在这种结合的方法中,当一个设备产生了一个自陷时,你可以使用网络管理工作站来查询该设备(假设它仍然是可到达的),以获得更多的信息。
二.系统概述
因为这个作业比较特殊,由于没有相应的实验环境,所以最初的作业要求显得不切实际,和助教老师商量过后,决定将该作业分为两块,一是实现mib viewer功能,即能够通过收发数据包取得任何oid所对应的mib值,二是通过一个静态的数据结构来仿真top发现的算法,因为这两者的结合加上相应的网络环境,就能够实现现实的网络top发现了,换句话说,实现了这两部分的内容,也就基本上达到了作业的要求。
下面分两部分说明:
1. Mib viewer
使用方法:
选中mib viewer标签,在target ip栏中输入希望查询的设备ip地址,在oid栏中填入希望查询的oid值(oid值的输入与选择的查询方法有关),选择想要的查询方法(Get,GetNext,GetBulk)…
Get:一次只读一条记录,而且对于目标oid肯定,例如,希望读取sysDescr的值,则oid值必须输入1.3.6.1.2.1.1.1.0。
GetNext:一次只读取一条记录,但是能读取不确定的oid所对应的信息,如输入1.3.6.1.2.1.1.1,也能读出对应的sysDescr值。
GetBulk:一次能读取多条数据,需要在对应的edit框中输入所需读取的信息数目,例如在oid中输入1.3.6.1.2.1.1,在edit栏中输入7,就能读出System组的所有7条信息。
效果图:
程序设计说明:
目前流行的snmp工具包主要有net-snmp,agent++,snmp++,和winsnmp,我用的是由微软提供的winsnmp开发包,因为其它的工具包要么不是免费的(如hp公司的snmp++和agent++),要么是针对linux系统开发的,对VC的支持不好,所以被迫选择了winsnmp,使用之后发现这个开发包很不好用,集成度太低,而且宏定意相当凌乱,总之,花了相当功夫才上手的。
我自己将winsnmp.h提供的api封装成一个CSnmp类,方便后面程序的开发,期中主要的函数有:
//构造函数
CSnmp();
主要封装了三个api:
//启动Snmp服务
SnmpStartup(nMajorVersion,nMinorVersion,nLevel,nTranslateMode,nRetransmitMode)
//设置传输模式 *注意,这里必须为V2以上版本,否则对很多功能不支持。
SnmpSetTranslateMode(SNMPAPI_UNTRANSLATED_V2)
//设置重传模式
SnmpSetRetransmitMode(SNMPAPI_ON)
//建立会话
bool CreateSession(HWND hWnd, UINT wMsg, CString& errorinfo);
//绑定变量列表
bool CreateVBL(LPCSTR string, smiLPVALUE pvalue,CString& errorinfo);
//追加绑定变量列表
bool SetVBL(LPCSTR string, CString& errorinfo);
//创建协议数据单元for get or get next
bool CreatePDU(smiINT PDU_type, CString& errorinfo);
//创建协议数据单元for getbulk
bool CreatePDU(smiINT PDU_type, CString& errorinfo, int a);
//发送数据包
bool Send(LPCSTR address,const char* password, CString& errorinfo);
//接收数据包并解析
bool Receive(LPTSTR name[30],smiLPVALUE value[30], CString& errorinfo);
期中主要包括:
//接受消息
SnmpRecvMsg(m_hSession,&srcEntity,&dstEntity,&context,&pPDU)
//获取数据包内的信息
SnmpGetPduData(pPDU,PDU_type,request_id,error_status,
error_index,&varbindlist)
//获取变量数目
m_nCount = SnmpCountVbl(varbindlist)
//获取变量的值
for(int i=1;i<=m_nCount;i++)
SnmpGetVb(varbindlist,i,pOid[i-1],value[i-1])
//获取变量相对应的oid值
for(i=0;i<m_nCount;i++)
{if(SnmpOidToStr(pOid[i],100,name[i]) == SNMPAPI_FAILURE)
//错误映射表…便于调试
void ErrorToString(unsigned long errorindex, CString &str);
实际使用时,主要是两个函数:
send(CString AgentIP, CString a,int b)//三个参数分别为目标ip,待查oid值,查找类型
按以下顺序调用CSnmp中的函数:
CreateSession(CNetView::m_hWnd,wMsg,errorinfo)//wMsg是自己定义的消息,用来联动
receive()函数
CreateVBL((LPCSTR)m_strOid[0].GetBuffer(0),NULL,errorinfo)
m_Snmp.CreatePDU(SNMP_PDU_GET,errorinfo)//共有三种查找方式,这里以get为例
m_Snmp.Send((LPCSTR)AgentIP,"public", errorinfo)
receive()
在成功调用CSnmp中的Receive(pOid,pValue,errorinfo)函数之后
用switch-case语句分析返回的信息内容,并加以记录和输出。
二.静态算法演示:
效果图:
说明:
主要是用自己定义的一个静态的数据结构来仿真网络top的发现算法。
算法描述:
在每次找到交换机的时候,对该交换机进行如下操作:
主要涉及oid:
Generated from OBJECT-TYPE definition found in rfc1213-mib2.asn1
OID value: 1.3.6.1.2.1.4.21.1.7
OID description:
ipRouteNextHop OBJECT-TYPE
SYNTAX IpAddress
ACCESS read-write
STATUS mandatory
DESCRIPTION
"The IP address of the next hop of this route.
(In the case of a route bound to an interface
which is realized via a broadcast media, the value
of this field is the agent's IP address on that
interface.)"
::= { ipRouteEntry 7 }
OID value: 1.3.6.1.2.1.4.21.1.8
OID description:
ipRouteType OBJECT-TYPE
SYNTAX INTEGER {
other(1),
invalid(2),
direct(3),
indirect(4)
}
ACCESS read-write
STATUS mandatory
DESCRIPTION
"The type of route. Note that the values
direct(3) and indirect(4) refer to the notion of
direct and indirect routing in the IP
architecture.
Setting this object to the value invalid(2) has
the effect of invalidating the corresponding entry
in the ipRouteTable object. That is, it
effectively dissasociates the destination
identified with said entry from the route
identified with said entry. It is an
implementation-specific matter as to whether the
agent removes an invalidated entry from the table.
Accordingly, management stations must be prepared
to receive tabular information from agents that
corresponds to entries not currently in use.
Proper interpretation of such entries requires
examination of the relevant ipRouteType object."
::= { ipRouteEntry 8 }
Generated from OBJECT-TYPE definition found in rfc1213-mib2.asn1
OID value: 1.3.6.1.2.1.4.21.1.11
OID description:
ipRouteMask OBJECT-TYPE
SYNTAX IpAddress
ACCESS read-write
STATUS mandatory
DESCRIPTION
"Indicate the mask to be logical-ANDed with the
destination address before being compared to the
value in the ipRouteDest field. For those systems
that do not support arbitrary subnet masks, an
agent constructs the value of the ipRouteMask by
determining whether the value of the correspondent
ipRouteDest field belong to a class-A, B, or C
network, and then using one of:
mask network
255.0.0.0 class-A
255.255.0.0 class-B
255.255.255.0 class-C
If the value of the ipRouteDest is 0.0.0.0 (a
default route), then the mask value is also
0.0.0.0. It should be noted that all IP routing
subsystems implicitly use this mechanism."
::= { ipRouteEntry 11 }
Generated from OBJECT-TYPE definition found in rfc1213-mib2.asn1
OID value: 1.3.6.1.2.1.1.7
OID description:
sysServices OBJECT-TYPE
SYNTAX INTEGER (0..127)
ACCESS read-only
STATUS mandatory
DESCRIPTION
"A value which indicates the set of services that
this entity primarily offers.
The value is a sum. This sum initially takes the
value zero, Then, for each layer, L, in the range
1 through 7, that this node performs transactions
for, 2 raised to (L - 1) is added to the sum. For
example, a node which performs primarily routing
functions would have a value of 4 (2^(3-1)). In
contrast, a node which is a host offering
application services would have a value of 72
(2^(4-1) + 2^(7-1)). Note that in the context of
the Internet suite of protocols, values should be
calculated accordingly:
layer functionality
1 physical (e.g., repeaters)
2 datalink/subnetwork (e.g., bridges)
3 internet (e.g., IP gateways)
4 end-to-end (e.g., IP hosts)
7 applications (e.g., mail relays)
For systems including OSI protocols, layers 5 and
6 may also be counted."
::= { system 7 }
OID value: 1.3.6.1.2.1.4.20.1.1
OID description:
ipAdEntAddr OBJECT-TYPE
SYNTAX IpAddress
ACCESS read-only
STATUS mandatory
DESCRIPTION
"The IP address to which this entry's addressing
information pertains."
::= { ipAddrEntry 1 }
OID value: 1.3.6.1.2.1.4.20.1.3
OID description:
ipAdEntNetMask OBJECT-TYPE
SYNTAX IpAddress
ACCESS read-only
STATUS mandatory
DESCRIPTION
"The subnet mask associated with the IP address of
this entry. The value of the mask is an IP
address with all the network bits set to 1 and all
the hosts bits set to 0."
::= { ipAddrEntry 3 }
主要静态数据结构:
iproutetype1[0][0]=4;//路由器接口所连接的设备类型
iproutetype1[0][1]=3;//3为交换机
iproutetype1[0][2]=3;//4为路由器
iproutetype1[0][3]=3;
iproutetype1[1][0]=4;
iproutetype1[1][1]=3;
iproutetype1[1][2]=3;
iproutetype1[1][3]=3;
iproutenexthop1[0][0]="202.120.1.2";//路由器接口所连接路由器的ip地址
iproutenexthop1[1][0]="202.120.1.1";
iproutedest1[0][1]="192.168.0.1";//路由器接口所连接交换机的ip地址
iproutedest1[0][2]="192.168.0.2";
iproutedest1[0][3]="192.168.0.3";
iproutedest1[1][1]="192.168.1.1";
iproutedest1[1][2]="192.168.1.2";
iproutedest1[1][3]="192.168.1.3";
routemask1[0][1]="255.255.255.0";//路由器接口所连接的交换机的子网掩码
routemask1[0][2]="255.255.255.0";
routemask1[0][3]="255.255.255.0";
routemask1[1][1]="255.255.255.0";
routemask1[1][2]="255.255.255.0";
routemask1[1][3]="255.255.255.0";
host_ip[0]="192.168.3.1";//第三层设备ip
host_ip[1]="192.168.3.2";
type[0]=76;//第三层设备的sysservice值
type[1]=32;
***更详细的代码解释请参见源程序注释。
参考资料:
1. MSDN
2. 《WinSNMP API规范》 北京佳合通信技术公司 王朋武
3. 《SNMP原理与应用》 上海交通大学 白英彩
4. http://www.alvestrand.no/ oid信息检索
5. 驱动开发论坛snmp版
展开阅读全文