深入理解Net-Snmp
上QQ阅读APP看书,第一时间看更新

2.8 例子

经过之前的学习,下面我们尝试定义一种消息格式,用于实现某种信息的获取和设置。该消息格式的定义需要实现下面的需求。

1)报文头:应该包含该消息格式版本的说明、通信共用的识别密码、考虑将来可能的扩展、命令类型标识;

2)报文内容:报文唯一标识、错误状态、发生错误的位置、对象名称与值的绑定;其中错误状态包括没有错误、报文太大、报文携带的对象不存在、报文携带对象的值不合法、报文中某个对象的值不可以被更改(当设置一个只读对象时)、其他未知错误。

3)支持多种命令:获取对象、设置对象、命令的响应等三种命令。

对于第一条需求,它看起来像下面的样子,如图2-2所示。

对于第二条需求,它看起来像下面的样子,如图2-3所示。

图2-2 报文头示意图

图2-3 报文内容示意图

实现方案如下:

1)可以在ASN.1中将以上的报文格式定义为一个模块。

2)图2-2中的字段,可以分别使用ASN.1中的基础类型定义。INTEGER、OCTEC STRING、any字段由于其的不确定性,可以使用ANY类型作为占位符。由于其中的各项内容有严格的顺序要求,可以考虑使用SEQUENCE构造数据类型实现这种语义。

3)由于该报文支持3种命令,每次的命令只为其中一种,所以可以使用CHOICE类型。

4)图2-3中的内容是报文的主要内容。涉及字段定义、结构定义。我们可以使用INTEGER定义字段RequestID、ErrorStatus、ErrorIndex;由于报文内容格式一致且有顺序要求,使用SEQUENCE类型表示这种语义。为了区分命令种类,需要给每个命令标记唯一的识别码,这可以使用标签类型来实现。在这里,我们使用上下文指定标签类和隐式的方式来定义。

5)VarBindList具有列表性质,使用SEQUENCE OF定义。

结果看起来大概会是以下的样子:

-- 模块的定义
MYEXAMPLE-SNMP DEFINITIONS ::= BEGIN
        IMPORTS  -- IMPORTS的使用方法
            ObjectName, ObjectSyntax FROM RFC1155-SMI;
        Message ::= SEQUENCE {
                      version  INTEGER {  version-1(0) },
                      community  OCTET STRING,
                      data    ANY      -- 扩展性考虑,见下面的PDUs
                    }
          -- 命令种类定义
          PDUs ::= CHOICE {
         get-request  GetRequest-PDU,
                      get-response  GetResponse-PDU,
                       set-request   SetRequest-PDU,
                     }
         GetRequest-PDU   ::= [0] IMPLICIT PDU
         GetResponse-PDU  ::= [2] IMPLICIT PDU
         SetRequest-PDU   ::= [3] IMPLICIT PDU
        PDU ::= SEQUENCE {
              RequestID ::=  INTEGER
                ErrorStatus ::=
                      INTEGER {
                         noError(0), tooBig(1),
                         noSuchName(2), badValue(3),
                         readOnly(4), genErr(5)
                      }
                ErrorIndex ::=  INTEGER
                -- 变量绑定
                VarBind ::= SEQUENCE {
                         name  ObjectName,  -- 对象名
                         value ObjectSyntax -- 对象值
                      }
                VarBindList ::=  SEQUENCE OF   VarBind
               }
        END -- 模块定义结束

实际上,该例子是仿照文献RFC1157中PDU定义的,其使用了本章大部分的知识,希望读者能明白各种数据类型的运用。如果把例子的讲解思路反过来的话,就是告诉读者如何阅读SNMP文献!