跳到主要内容

4. Protocol Specification

4. 协议规范​

网络管理协议是一种应用协议,通过该协议可以检查或改变代理的MIB的变量.

协议实体之间的通信是通过消息交换来完成的,每个消息都使用 ASN.1 的基本编码规则(如第 3.2.2 节中所讨论的)在单个 UDP 数据报中完整且独立地表示. 消息由版本标识符,SNMP 团体名称和协议数据单元 (PDU) 组成.协议实体在与其关联的主机上的 UDP 端口 161 接收除报告陷阱之外的所有消息(即,除包含 Trap-PDU 的消息之外的所有消息)的消息.应在 UDP 端口 162 上接收报告陷阱的消息以进行进一步处理. 该协议的实现不需要接受长度超过 484 个八位位组的消息. 但是,建议在可行的情况下实现支持更大的数据报.

SNMP 的所有实现都必须支持五种 PDU:GetRequest-PDU,GetNextRequest-PDU,GetResponse-PDU,SetRequest-PDU 和 Trap-PDU.

    RFC1157-SNMP DEFINITIONS ::= BEGIN

IMPORTS
ObjectName, ObjectSyntax, NetworkAddress, IpAddress, TimeTicks
FROM RFC1155-SMI;

-- top-level message

Message ::=
SEQUENCE {
version -- version-1 for this RFC
INTEGER {
version-1(0)
},

community -- community name
OCTET STRING,

data -- e.g., PDUs if trivial
ANY -- authentication is being used
}
-- protocol data units

PDUs ::=
CHOICE {
get-request
GetRequest-PDU,

get-next-request
GetNextRequest-PDU,

get-response
GetResponse-PDU,

set-request
SetRequest-PDU,

trap
Trap-PDU
}

-- the individual PDUs and commonly used
-- data types will be defined later

END

4.1. 过程要素​

本节描述实现 SNMP 的协议实体的操作.但请注意,它无意于限制任何一致性实现的内部架构.

在下文中,使用术语传输地址. 对于 UDP,传输地址由 IP 地址和 UDP 端口组成. 其他传输服务可用于支持 SNMP. 在这些情况下,应相应地定义传输地址.

生成消息的协议实体的顶层操作如下:

  1. 它首先构造适当的 PDU,例如 GetRequest-PDU,作为 ASN.1 对象.

  2. 然后,它将这个 ASN.1 对象以及团体名称,源传输地址和目标传输地址传递给实现所需身份验证方案的服务. 此身份验证服务返回另一个 ASN.1 对象.

  3. 然后,协议实体使用团体名称和生成的 ASN.1 对象构造 ASN.1 消息对象.

  4. 然后使用 ASN.1 的基本编码规则序列化这个新的 ASN.1 对象,然后使用传输服务发送到对等协议实体.

类似地,接收消息的协议实体的顶层动作如下:

  1. 它对传入数据报执行基本解析,以构建与 ASN.1 Message 对象相对应的 ASN.1 对象.如果解析失败,它将丢弃数据报并且不执行进一步的操作.

  2. 然后它验证 SNMP 消息的版本号.如果不匹配,它将丢弃数据报并且不执行进一步的操作.

  3. 然后,协议实体将 ASN.1 消息对象中找到的团体名称和用户数据以及数据报的源和目标传输地址一起传递给实现所需身份验证方案的服务. 该实体返回另一个 ASN.1 对象,或发出身份验证失败信号. 在后一种情况下,协议实体注意到此失败,(可能)生成陷阱,并丢弃数据报并且不执行进一步的操作.

  4. 然后,协议实体对从认证服务返回的 ASN.1 对象执行基本解析,以构建与 ASN.1 PDU 对象相对应的 ASN.1 对象. 如果解析失败,它将丢弃数据报并且不执行进一步的操作. 否则,使用命名的 SNMP 社区,选择适当的配置文件,并相应地处理 PDU. 如果此处理的结果是返回消息,则发送响应消息的源传输地址应与原始请求消息发送到的目标传输地址相同.

4.1.1. 公共结构​

在介绍协议的六种 PDU 类型之前,有必要考虑一些经常使用的 ASN.1 构造:

                  -- request/response information
                  RequestID ::=
INTEGER
                  ErrorStatus ::=
INTEGER {
noError(0),
tooBig(1),
noSuchName(2),
badValue(3),
readOnly(4)
genErr(5)
}
                  ErrorIndex ::=
INTEGER
                  -- variable bindings
                  VarBind ::=
SEQUENCE {
name
ObjectName,

value
ObjectSyntax
}
                  VarBindList ::=
SEQUENCE OF
VarBind

RequestID 用于区分未完成的请求. 通过使用 RequestID,SNMP 应用程序实体可以将传入响应与未完成的请求关联起来. 在使用不可靠的数据报服务的情况下,RequestID 还提供了一种识别网络重复消息的简单方法.

ErrorStatus 的非零实例用于指示处理请求时发生异常. 在这些情况下,ErrorIndex 可以通过指示列表中的哪个变量导致异常来提供附加信息.

术语"变量"指的是被管对象的实例. 变量绑定(或 VarBind)是指变量名称与变量值的配对. VarBindList 是变量名称和相应值的简单列表. 一些 PDU 只关心变量的名称而不关心它的值(例如,GetRequest-PDU). 在这种情况下,协议实体将忽略绑定的值部分. 但是,值部分仍必须具有有效的 ASN.1 语法和编码. 建议将 ASN.1 值 NULL 用于此类绑定的值部分.

4.1.2. GetRequest-PDU​

GetRequest-PDU的形式为:

                  GetRequest-PDU ::=
[0]
IMPLICIT SEQUENCE {
request-id
RequestID,

error-status -- always 0
ErrorStatus,

error-index -- always 0
ErrorIndex,

variable-bindings
VarBindList
}

GetRequest-PDU 仅在其 SNMP 应用实体的请求时由协议实体生成.

收到 GetRequest-PDU 后,接收协议实体根据以下列表中的任何适用规则进行响应:

  1. 如果 variable-bindings 字段中任一对象的名称与相关 MIB 视图内可用于 get 操作的某个对象名称不完全匹配,接收实体就向接收消息的发起方发送形式相同的 GetResponse-PDU,但 error-status 字段的值为 noSuchName,error-index 字段的值为接收消息中该对象名称组件的索引.

  2. 如果 variable-bindings 字段中命名的任一对象属于聚合类型(定义见 SMI),接收实体就向接收消息的发起方发送形式相同的 GetResponse-PDU,但 error-status 字段的值为 noSuchName,error-index 字段的值为接收消息中该对象名称组件的索引.

  3. 如果如下所述生成的GetResponse-PDU的大小超出本地限制,则接收实体向接收到的消息的发起者发送相同形式的GetResponse-PDU,除了error-status字段的值为tooBig,并且error-index字段的值为0之外.

  4. 如果由于前述规则均未涵盖的原因,无法检索 variable-bindings 字段中命名的任一对象的值,接收实体就向接收消息的发起方发送形式相同的 GetResponse-PDU,但 error-status 字段的值为 genErr,error-index 字段的值为接收消息中该对象名称组件的索引.

如果前述规则均不适用,则接收协议实体将 GetResponse-PDU 发送到所接收消息的发起者,使得对于所接收消息的变量绑定字段中指定的每个对象,GetResponse-PDU 的相应组件表示该变量的名称和值. GetResponse-PDU的错误状态字段的值是noError并且error-index字段的值为零. GetResponse-PDU 的 request-id 字段的值是接收到的消息的值.

4.1.3. GetNextRequest-PDU​

GetNextRequest-PDU 的形式与 GetRequest-PDU 的形式相同,除了 PDU 类型的指示之外. 在 ASN.1 语言中:

                  GetNextRequest-PDU ::=
[1]
IMPLICIT SEQUENCE {
request-id
RequestID,
error-status -- always 0
ErrorStatus,

error-index -- always 0
ErrorIndex,

variable-bindings
VarBindList
}

GetNextRequest-PDU 仅在其 SNMP 应用实体的请求时由协议实体生成.

收到 GetNextRequest-PDU 后,接收协议实体根据以下列表中的任何适用规则进行响应:

  1. 如果 variable-bindings 字段中的任一对象名称在字典序上不先于相关 MIB 视图内可用于 get 操作的某个对象名称,接收实体就向接收消息的发起方发送形式相同的 GetResponse-PDU,但 error-status 字段的值为 noSuchName,error-index 字段的值为接收消息中该对象名称组件的索引.

  2. 如果如下所述生成的GetResponse-PDU的大小超出本地限制,则接收实体向接收到的消息的发起者发送相同形式的GetResponse-PDU,除了error-status字段的值为tooBig,并且error-index字段的值为0之外.

  3. 如果由于前述规则均未涵盖的原因,无法检索 variable-bindings 字段中命名对象的字典序后继对象值,接收实体就向接收消息的发起方发送形式相同的 GetResponse-PDU,但 error-status 字段的值为 genErr,error-index 字段的值为接收消息中该对象名称组件的索引.

如果前述规则均不适用,则接收协议实体将 GetResponse-PDU 发送到所接收消息的发起者,使得对于所接收消息的 variable-bindings 字段中的每个名称,GetResponse-PDU 的相应组件表示该对象的名称和值,该对象的名称是按照相关 MIB 视图中可用于 get 操作的所有对象的名称的字典顺序,以及给定组件的名称字段的值,该值的直接后继者. GetResponse-PDU的error-status字段的值为noError,并且errorindex字段的值为0. GetResponse-PDU的request-id字段的值是接收到的消息的值.

4.1.3.1. 表遍历示例​

GetNextRequest-PDU 的一项重要用途是遍历 MIB 内的概念信息表.这种类型的 SNMP 消息的语义与用于识别 MIB 中对象类型的各个实例的特定于协议的机制一起,提供对 MIB 中相关对象的访问,就好像它们享受表格组织一样.

通过下面概述的 SNMP 交换,SNMP 应用实体可以提取特定网络元素的路由表中每个条目的目标地址和下一跳网关.假设该路由表有三个条目:

         Destination                     NextHop         Metric
         10.0.0.99                       89.1.1.42       5
9.1.2.3 99.0.0.3 3
10.0.0.51 89.1.1.42 5

管理站向 SNMP 代理发送一个 GetNextRequest-PDU,其中包含指示的 OBJECT IDENTIFIER 值作为请求的变量名称:

   GetNextRequest ( ipRouteDest, ipRouteNextHop, ipRouteMetric1 )

SNMP 代理使用 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 )

SNMP 代理响应:

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

管理站继续:

                 GetNextRequest ( ipRouteDest.10.0.0.51,
ipRouteNextHop.10.0.0.51,
ipRouteMetric1.10.0.0.51 )

SNMP 代理响应:

                 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 )

由于表中没有更多条目,因此 SNMP 代理返回已知对象名称的字典顺序中的下一个对象. 该响应向管理站发出路由表结束的信号.

4.1.4. GetResponse-PDU​

GetResponse-PDU 的形式与 GetRequest-PDU 的形式相同,除了 PDU 类型的指示之外. 在 ASN.1 语言中:

                  GetResponse-PDU ::=
[2]
IMPLICIT SEQUENCE {
request-id
RequestID,
error-status
ErrorStatus,

error-index
ErrorIndex,

variable-bindings
VarBindList
}

GetResponse-PDU 仅在收到 GetRequest-PDU,GetNextRequest-PDU 或 SetRequest-PDU 时由协议实体生成,如本文档其他部分所述.

接收到 GetResponse-PDU 后,接收协议实体将其内容呈现给其 SNMP 应用实体.

4.1.5. SetRequest-PDU​

SetRequest-PDU 的形式与 GetRequest-PDU 的形式相同,除了 PDU 类型的指示之外. 在 ASN.1 语言中:

                  SetRequest-PDU ::=
[3]
IMPLICIT SEQUENCE {
request-id
RequestID,

error-status -- always 0
ErrorStatus,

error-index -- always 0
ErrorIndex,

variable-bindings
VarBindList
}

SetRequest-PDU 仅在其 SNMP 应用实体的请求时由协议实体生成.

收到 SetRequest-PDU 后,接收实体根据下表中的任何适用规则进行响应:

  1. 如果 variable-bindings 字段中命名的任一对象不能用于相关 MIB 视图中的 set 操作,接收实体就向接收消息的发起方发送形式相同的 GetResponse-PDU,但 error-status 字段的值为 noSuchName,error-index 字段的值为接收消息中该对象名称组件的索引.

  2. 如果对于 variable-bindings 字段中命名的任一对象,value 字段的内容按照 ASN.1 语法未体现出与该变量要求相符的类型、长度和值,接收实体就向接收消息的发起方发送形式相同的 GetResponse-PDU,但 error-status 字段的值为 badValue,error-index 字段的值为接收消息中该对象名称的索引.

  3. 如果如下所述生成的GetResponse 类型消息的大小超出本地限制,则接收实体向接收到的消息的发起者发送相同形式的GetResponse-PDU,除了error-status字段的值为tooBig,并且error-index字段的值为0之外.

  4. 如果由于前述规则均未涵盖的原因,无法更改 variable-bindings 字段中命名的任一对象的值,接收实体就向接收消息的发起方发送形式相同的 GetResponse-PDU,但 error-status 字段的值为 genErr,error-index 字段的值为接收消息中该对象名称组件的索引.

如果上述规则均不适用,则对于在接收到的消息的 variable-bindings 字段中命名的每个对象,将相应的值分配给变量. SetRequest-PDU 指定的每个变量赋值应该像针对同一消息中指定的所有其他赋值同时设置一样进行.

然后,接收实体向接收到的消息的发起者发送相同形式的GetResponse-PDU,除了所生成的消息的error-status字段的值为noError并且error-index字段的值为0之外.

4.1.6. Trap-PDU​

Trap-PDU的形式为:

     Trap-PDU ::=
[4]

IMPLICIT SEQUENCE {
enterprise -- type of object generating
-- trap, see sysObjectID in [5]
OBJECT IDENTIFIER,

agent-addr -- address of object generating
NetworkAddress, -- trap

generic-trap -- generic trap type
INTEGER {
coldStart(0),
warmStart(1),
linkDown(2),
linkUp(3),
authenticationFailure(4),
egpNeighborLoss(5),
enterpriseSpecific(6)
},

specific-trap -- specific code, present even
INTEGER, -- if generic-trap is not
-- enterpriseSpecific

time-stamp -- time elapsed between the last
TimeTicks, -- (re)initialization of the network
-- entity and the generation of the
trap

variable-bindings -- "interesting" information
VarBindList
}

Trap-PDU仅在SNMP应用实体的请求时由协议实体生成. SNMP 应用程序实体选择 SNMP 应用程序实体的目标地址的方式是特定于实现的.

接收到 Trap-PDU 后,接收协议实体将其内容呈现给其 SNMP 应用实体. Trap-PDU 的 variable-bindings 组件的重要性是特定于实现的.

generic-trap字段的值的解释是:

4.1.6.1. coldStart Trap​

coldStart(0) 陷阱表示发送协议实体正在重新初始化自身,从而可能会更改代理的配置或协议实体实现.

4.1.6.2. warmStart Trap​

warmStart(1) 陷阱表示发送协议实体正在重新初始化自身,这样代理配置和协议实体实现都不会更改.

4.1.6.3. linkDown Trap​

linkDown(2) 陷阱表示发送协议实体认识到代理配置中表示的通信链路之一出现故障.

linkDown 类型的 Trap-PDU 包含受影响接口的 ifIndex 实例的名称和值作为其 variable-bindings 的第一个元素.

4.1.6.4. linkUp Trap​

linkUp(3) 陷阱表示发送协议实体识别出代理配置中表示的某条通信链路已经恢复.

linkUp 类型的 Trap-PDU 包含受影响接口的 ifIndex 实例的名称和值作为其 variable-bindings 的第一个元素.

4.1.6.5. authenticationFailure Trap​

authenticationFailure(4) 陷阱表示发送协议实体是未正确验证的协议消息的收件人. 虽然 SNMP 的实现必须能够生成此陷阱,但它们还必须能够通过特定于实现的机制抑制此类陷阱的发射.

4.1.6.6. egpNeighborLoss Trap​

egpNeighborLoss(5) 陷阱表示某个以发送协议实体为 EGP 对等方的 EGP 邻居已被标记为不可用,并且该对等关系不再存在.

egpNeighborLoss 类型的 Trap-PDU 包含受影响邻居的 egpNeighAddr 实例的名称和值作为其 variable-bindings 的第一个元素.

4.1.6.7. enterpriseSpecific Trap​

enterpriseSpecific(6) 陷阱表示发送协议实体认识到某些企业特定事件已发生. specific-trap 字段标识发生的特定陷阱.


Return: RFC 1157 Home