轻松学习SNMP协议之入门篇


1. SNMP治理模型
1.1. 什么是SNMP
SNMP(Simple Network Management Protocol)是被广泛接受并投入使用的工业标准 , 它的目标是保证治理信息在任意两点中传送 , 便于网络治理员在网络上的任何节点检索信息 , 进行修改 , 寻找故障;完成故障诊断 , 容量规划和报告生成 。它采用轮询机制 , 提供最基本的功能集 。最适合小型、快速、低价格的环境使用 。它只要求无证实的传输层协议UDP , 受到许多产品的广泛支持 。SNMP在TCP/IP协议族中的地位如下图:
 
1.2. SNMP的基本操作:
 
SNMP以GET-SET方式替代了复杂的命令集 , 利用基本操作演绎出全部操作 。用户可以采用治理信息库标准或按标准的方式来定义自己的治理信息库(MIB) 。这样做的好处是:通过降低占网管系统中大多数的代理部件的成本来降低整个网管系统的成本 。
1.3. 网管站和代理
网管站(NMS)对网络设备发送各种查询报文 , 并接收来自被管设备的响应及陷阱(trap)报文 , 将结果显示出来 。代理(agent)是驻留在被管设备上的一个进程 , 负责接受、处理来自网管站的请求报文 , 然后从设备上其他协议模块中取得治理变量的数值 , 形成响应报文 , 反送给NMS 。在一些紧急情况下 , 如接口状态发生改变 , 呼叫成功等时候 , 主动通知NMS(发送陷阱TRAP报文) 。
他们的关系如下图:
 
SNMP就是用来规定NMS和Agent之间是如何传递治理信息的应用层协议 。
1.4. ASN.1和SMI
SNMP是应用层协议 , 它要求两端的协议实体交换各种报文 , 而低层要求用户数据都是BYTE序列 , 这就产生了一个问题: SNMP协议实体如何从接受到的一个BYTE序列中识别出报文又如何把一个用内部数据结构表示的报文转换成一个可供发送的BYTE序列 , 也就是编解码问题 。
解决这个问题 , 就需要一个定义从实际的软件数据结构中抽象出来的数据类型的表示方法 , 称为抽象句法 。
ASN.1就是用来描述抽象记法的语言 , 事实上可应用与任何协议层 , 在它的基础上 , 通过规定编码规则 , 就可以确定数据在传送中的八比特组的值 。
SMI(StrUCt of Management Imformation) , 通过定义一个宏OBJECT-TYPE , 规定了治理对象的表示方法 , 从这个意义上说 , 它是ASN.1的一个子集 。另外它还定义了几个SNMP常用的基本类型和值 。
MIB (Management Imformation Base), 是所监控网络设备的标准变量定义的集合 。SNMP用层次结构命名方案来识别治理对象 , 就象一棵树 , 树的节点表示治理对象 , 它可以用从根开始的一条路径来无二义的识别 。见下图:
 
治理对象B可以用一串数字唯一确定{1.2.1.1} 这串数字是治理对象的object identifier(客体标识符) 。通过object identifier可确定从根到 B的一条路径 。
治理对象 A 的object identifier 是{1.2.1.1.5} , 或{B 5},后一种表示方法表明A是B的第5棵孩子 。
在agent中这棵树是用较复杂的数据结构来实现的 , 幸运的是 , 建树这个工作可由MIB编译器完成 。在树的叶节点中 , 存放有访问函数的指针 , Agent就是通过调用这些函数来从相关模块取得治理变量的值的 。
1.5. SNMP报文
SNMP报文结构如下:(编码之前)
 
SNMP共有5中报文 , 所以其PDU也有5中 , 仅以GetRequest-PDU为例
 
2.治理变量的表示
治理变量表示治理对象类型在某一时刻的值(或称该类型的实例) , SNMP以治理变量作为操作对象 。
治理变量的表示方法是这样规定的:形如x.y , 其中x是治理对象的object identifer 。y是能唯一确定对象类型值的一组数字 , 在非表型变量中为0 , 在表型变量中是这个表的索引 , 比如接口表中的接口号 , 或路由表中的目的网络地址等等。如:在MIB文件里定义了ipAdEntNetMask这一治理对象 , 其object identifier为1.3.6.1.1.5.6.1.3它是个路由表中的一项 , 它的一个实例就是路由表中某一行的子网掩码 , 假如这行的索引、目的网络地址为129.102.1.0 。则这个变量名是:1.3.6.1.1.5.6.1.3.129.102.1.0 。在以后的说明中 , 为了方便 , 把唯一确定治理变量的一组数字 , 也就是x.y中的y称作实例 。
3.SNMP的运行过程
驻留在被管设备上的AGENT从UDP端口161接受来自网管站的串行化报文 , 经解码、团体名验证、分析得到治理变量在MIB树中对应的节点 , 从相应的模块中得到治理变量的值 , 再形成响应报文 , 编码发送回网管站 。网管站得到响应报文后 , 再经同样的处理 , 最终显示结果 。
下面根据RFC1157具体介绍Agent接受到报文后采取的动作:
首先解码生成用内部数据结构表示的报文 , 解码依据ASN.1的基本编码规则 , 假如在此过程中出现错误导致解码失败则丢弃该报文 , 不做进一步处理 。
第二步:将报文中的版本号取出 , 假如与本Agent支持的SNMP版本不一致 , 则丢弃该报文 , 不做进一步处理 。当前北研的数据通信产品只支持SNMP版本1 。
第三步:将报文中的团体名取出 , 此团体名由发出请求的网管站填写 。如与本设备认可的团体名不符 , 则丢弃该报文 , 不做进一步处理 , 同时产生一个陷阱报文 。SNMPv1只提供了较弱的安全措施 , 在版本3中这一功能将大大加强 。
第四步:从通过验证的ASN.1对象中提出协议数据单元PDU , 假如失败 , 丢弃报文 , 不做进一不处理 。否则处理PDU , 结果将产生一个报文 , 该报文的发送目的地址应同收到报文的源地址一致 。
根据不同的PDU , SNMP协议实体将做不同的处理:
1.6. GetRequest PDU:
第一种情况:假如PDU中的变量名在本地维护的MIB树中不存在,则接受到这个PDU的协议实体将向发出者发送一个GetResponse报文 , 其中的PDU与源PDU只有一点不同:将ERROR-STATUS置为noSuchName,并在ERROR-INDEX中指出产生该变量在变量LIST中的位置 。
第二种情况:假如本地协议实体将产生的响应报文的长度大于本地长度限制 , 将向该PDU的发出者发送一个GetResponse报文 , 该PDU除了ERROR-STATUS置为tooBig , ERROR-INDEX置为0以外 , 与源PDU相同 。
第三种情况:假如本地协议实体因为其他原因不能产生正确的响应报文 , 将向该PDU的发出者发送一个GetResponse报文 , 该PDU除了ERROR-STATUS置为genErr , ERROR-INDEX置为出错变量在变量LIST中的位置 , 其余与源PDU相同 。
第四中情况:假如上面的情况都没有发生 , 则本地协议实体向该PDU的发出者发送一个GetResponse报文 , 该PDU中将包含变量名和相应值的对偶表 , ERROR-STATUS为noError,ERROR-INDEX为0 , request-id域的值应与收到PDU的request-id相同 。
1.7. GetNextRequest PDU
GetNextRequest PDU的最重要的功能是表的遍历 , 这种操作受到了前面所说的治理变量的表示方法的支持 , 从而可以访问一组相关的变量 , 就好象他们在一个表内 。
下面通过一个例子解释表遍历的过程:
被管设备维护如下路由表:
Destination NextHop Metric
10.0.0.9989.1.1.425
9.1.2.3 99.0.0.33
10.0.0.5189.1.1.425
假设网管站欲取得这张路由表的信息 , 该表的索引是目的网络地址 。
网管站向被管设备发送一个GetNextRequest PDU,其中的受管对象的标识如下
GetNextRequest(ipRouteDest, ipRouteNextHop, ipRouteMetric1)
SNMP agent响应如下GetResponse PDU:
GetResponse (( ipRouteDest.9.1.2.3 = "9.1.2.3" ),
( ipRouteNextHop.9.1.2.3 = "99.0.0.3" ),( ipRouteMetric1.9.1.2.3 = 3 ))
网管站继续:
GetNextRequest ( ipRouteDest.9.1.2.3,ipRouteNextHop.9.1.2.3,ipRouteMetric1.9.1.2.3 )
agent响应:
GetResponse((ipRouteDest.10.0.0.51="10.0.0.51"),(ipRouteNextHop.10.0.0.51="89.1.1.42"),( ipRouteMetric1.10.0.0.51 = 5 ))
值得注重的是agent必须能够确定下一个治理变量名 , 以保证所有变量能被取到且只被取到一次 。
网管站继续:
GetNextRequest ( ipRouteDest.10.0.0.51,ipRouteNextHop.10.0.0.51,ipRouteMetric1.10.0.0.51 )
agent响应:GetResponse (( ipRouteDest.10.0.0.99 = "10.0.0.99" ),( ipRouteNextHop.10.0.0.99 = "89.1.1.42" ),( ipRouteMetric1.10.0.0.99 = 5 ))
网管站继续:
GetNextRequest(ipRouteDest.10.0.0.99,ipRouteNextHop.10.0.0.99,ipRouteMetric1.10.0.0.99)
这时因为路由表中所有的行都被取遍 , agent因返回路由表对象的下一字典后继即该治理对象在MIB树中的后序遍历的直接后继 。这里应是nettoMediaIndex , 治理对象的OBJECT IDENTIFIER 。这个响应通知网管站对表的遍历已经完成 。
1.8. GetResponse PDU
GetResponse PDU只有当受到getRequest GetNextRequest SetRequest才由协议实体产生 , 网管站收到这个PDU后 , 应显示其结果 。
1.9. SetRequest PDU
SetRequest PDU除了PDU类型标识以外 , 和GetRequest相同 , 当需要对被管变量进行写操作时 , 网管站侧的协议实体将生成该PDU 。
对SetRequest的响应将根据下面情况分别处理:
1.假如是关于一个只读变量的设置请求 , 则收到该PDU的协议实体产生一个GetReponse报文 , 并置error status为noSuchName, error index的值是错误变量在变量list中的位置 。
2.假如被管设备上的协议实体收到的PDU中的变量对偶中的值 , 类型、长度不符和要求 , 则收到该PDU的协议实体产生一个GetReponse报文 , 并置error status为badValue, error index的值是错误变量在变量list中的位置 。
3.假如需要产生的GetReponse报文长度超过了本地限制 , 则收到该PDU的协议实体产生一个GetReponse报文 , 并置error status为tooBig, error index的值是0 。
4.假如是其他原因导致SET失败 , 则收到该PDU的协议实体产生一个GetReponse报文 , 并置error status为genErr, error index的值是错误变量在变量list中的位置 。
假如不符合上面任何情况 , 则agent将把治理变量设置收到的PDU中的相应值 , 这往往可以改变被管设备的运行状态 。同时产生一个GetResponse PDU , 其中error status置为noError,error index的值为0 。
1.10. Trap PDU
Trap PDU的有如下的形式
 
Trap是被管设备碰到紧急情况时主动向网管站发送的消息 。网管站收到trapPDU后要将起变量对偶表中的内容显示出来 。一些常用的trap类型有冷、热启动 , 链路状态发生变化等 。
4. SNMP MIB编译器的功能
MIB编译器是Agent开发的一个工具 , 一个Agent的开发者首先面对的是一个MIB文件 , 其中是用ASN.1描述的治理对象集 。MIB编译器要把这个文件转换成相应的C语言源文件 。MIB编译器可极大的提供Agent的开发效率 。