3. 过程要素 (Elements Of Procedure)
以下各节描述了五种SNMP应用类型在生成和处理SNMP消息时遵循的过程。
3.1. 命令生成器应用 (Command Generator Applications)
命令生成器应用使用SNMP消息处理子系统将SNMP消息传递给远程SNMP应用。
命令生成器必须能够确定远程应用的传输域和传输地址。实现此功能的方法取决于实现,不在本文档范围内。
命令生成器必须能够确定与远程应用通信时使用的适当SNMP消息参数(消息处理模型、安全模型、安全级别和安全名称)。实现此功能的方法取决于实现,不在本文档范围内。
3.1.1. 生成命令请求 (Generating a Command Request)
要发送SNMP命令请求,命令生成器应用:
-
使用其本地配置信息确定:
- 传输域和传输地址
- 消息处理模型
- 安全模型
- 安全名称
- 安全级别
- 上下文引擎ID (contextEngineID)
- 上下文名称 (contextName)
- 适当的PDU (GetRequest、GetNextRequest、GetBulkRequest或SetRequest)
-
调用消息处理子系统的发送PDU原语,传递:
- 传输域和传输地址
- 消息处理模型
- 安全模型
- 安全名称
- 安全级别
- contextEngineID
- contextName
- PDU
-
消息处理子系统返回状态指示。如果返回错误,命令生成器应适当处理该错误。
3.1.2. 处理响应 (Processing a Response)
当命令生成器接收到响应时:
-
消息处理子系统调用命令生成器的接收PDU原语,传递:
- 消息处理模型
- 安全模型
- 安全名称
- 安全级别
- contextEngineID
- contextName
- PDU
- 最大大小 (maxSizeResponseScopedPDU)
- 状态信息
-
命令生成器验证响应是否与未完成的请求匹配(通过request-id)。
-
命令生成器检查响应中的error-status。如果error-status字段非零,则发生了错误。
-
命令生成器处理响应中的variable-bindings列表。
3.1.3. 超时和重试 (Timeouts and Retries)
如果在合理时间内未收到响应,命令生成器可以重新传输请求。重试次数和超时值由本地配置或策略确定。
对于可靠的传输协议(如TCP),传输层本身可能提供重传。在这种情况下,应用层重试可能是不必要的或不适当的。
3.2. 命令响应器应用 (Command Responder Applications)
命令响应器应用接收SNMP命令请求并生成适当的响应。
3.2.1. 处理请求 (Processing a Request)
当命令响应器接收到请求时:
-
消息处理子系统调用命令响应器的接收PDU原语,传递:
- 消息处理模型
- 安全模型
- 安全名称
- 安全级别
- contextEngineID
- contextName
- PDU
- 最大大小 (maxSizeResponseScopedPDU)
- 状态信息
-
命令响应器验证contextEngineID是否标识本地SNMP引擎。如果不是,则丢弃该请求。
-
命令响应器使用访问控制子系统(如RFC 3415中定义的VACM)来确定安全名称是否被授权执行请求的操作。
-
命令响应器处理PDU:
- GetRequest: 检索请求的MIB对象的值
- GetNextRequest: 检索按字典顺序位于请求对象名称之后的下一个MIB对象
- GetBulkRequest: 执行优化的多变量检索
- SetRequest: 修改指定MIB对象的值
-
命令响应器构造包含以下内容的响应PDU:
- 与请求相同的request-id
- Error-status (noError或适当的错误代码)
- Error-index (如果发生错误,指示哪个variable-binding导致了错误)
- Variable-bindings列表 (对于Get操作,包含检索到的值;对于Set操作,包含设置的变量)
3.2.2. 生成响应 (Generating a Response)
命令响应器通过以下方式生成响应:
-
构造包含适当的error-status、error-index和variable-bindings列表的Response-PDU。
-
调用消息处理子系统的返回响应PDU原语,传递:
- 消息处理模型 (与请求相同)
- 安全模型 (与请求相同)
- 安全名称 (与请求相同)
- 安全级别 (与请求相同)
- contextEngineID (与请求相同)
- contextName (与请求相同)
- PDU (响应PDU)
- 最大大小 (来自请求的maxSizeResponseScopedPDU)
- 状态引用 (从请求处理中获得)
-
消息处理子系统处理响应消息的格式化和传输。
3.2.3. 错误处理 (Error Handling)
如果在处理请求时发生错误,命令响应器必须在响应PDU中设置适当的error-status:
- tooBig: 响应消息过大,无法在最大消息大小约束内传输
- noSuchName: 请求的对象不存在 (仅SNMPv1)
- badValue: 提供的值不适合请求的操作 (仅SNMPv1)
- readOnly: 尝试修改只读对象
- genErr: 发生一般错误
- noAccess: 访问被拒绝 (SNMPv2及更高版本)
- wrongType: 变量的类型错误 (SNMPv2及更高版本)
- wrongLength: 值的长度错误 (SNMPv2及更高版本)
- wrongEncoding: 值的编码错误 (SNMPv2及更高版本)
- wrongValue: 值不正确 (SNMPv2及更高版本)
- noCreation: 不允许创建 (SNMPv2及更高版本)
- inconsistentValue: 值不一致 (SNMPv2及更高版本)
- resourceUnavailable: 资源不可用 (SNMPv2及更高版本)
- commitFailed: 提交失败 (SNMPv2及更高版本)
- undoFailed: 撤消失败 (SNMPv2及更高版本)
- authorizationError: 授权错误 (SNMPv2及更高版本)
- notWritable: 对象不可写 (SNMPv2及更高版本)
- inconsistentName: 名称不一致 (SNMPv2及更高版本)
3.3. 通知发起者应用 (Notification Originator Applications)
通知发起者应用生成SNMP通知消息(陷阱或通知请求)。
3.3.1. 生成通知 (Generating a Notification)
要发送SNMP通知,通知发起者:
-
确定应接收此通知的管理目标集。这通常通过查询SNMP-TARGET-MIB和SNMP-NOTIFICATION-MIB来完成。
-
对于每个选定的管理目标:
a. 确定传输域和传输地址
b. 确定SNMP消息参数:
- 消息处理模型
- 安全模型
- 安全名称
- 安全级别
c. 确定通知类型(陷阱或通知)
d. 构造适当的PDU:
- SNMPv2-Trap-PDU: 用于未确认的通知
- InformRequest-PDU: 用于已确认的通知
e. PDU应包含:
- sysUpTime.0变量(引擎启动以来的时间)
- snmpTrapOID.0变量(通知的对象标识符)
- 通知的附加variable-bindings
f. 调用消息处理子系统的发送PDU原语
3.3.2. 处理对通知请求的响应 (Processing a Response to an Inform Request)
如果通知类型是通知(InformRequest-PDU),通知发起者必须等待响应:
-
如果在超时期限内收到响应:
- 验证响应是否与未完成的通知请求匹配(通过request-id)
- 检查error-status
- 确认通知已成功传递
-
如果在超时期限内未收到响应:
- 根据配置的重试策略,可以重新传输通知请求
- 或者,在本地记录失败并放弃此传递尝试
-
对于陷阱(SNMPv2-Trap-PDU),不期望响应,因此通知发起者在发送后立即完成。
3.4. 通知接收器应用 (Notification Receiver Applications)
通知接收器应用接收SNMP通知消息。
3.4.1. 处理接收到的通知 (Processing a Received Notification)
当通知接收器接收到通知时:
-
消息处理子系统调用通知接收器的接收PDU原语,传递:
- 消息处理模型
- 安全模型
- 安全名称
- 安全级别
- contextEngineID
- contextName
- PDU
- 最大大小
- 状态信息
-
通知接收器提取通知信息:
- sysUpTime.0 (时间戳)
- snmpTrapOID.0 (通知类型)
- 附加variable-bindings (通知数据)
-
通知接收器根据本地策略处理通知:
- 记录到日志文件
- 显示警报
- 触发自动响应操作
- 转发到其他管理系统
3.4.2. 响应通知请求 (Responding to an Inform Request)
如果接收到InformRequest-PDU,通知接收器必须生成响应:
-
构造包含以下内容的Response-PDU:
- 与请求相同的request-id
- Error-status (通常为noError)
- Error-index (通常为0)
- Variable-bindings列表 (通常与请求中的相同)
-
调用消息处理子系统的返回响应PDU原语以发送响应。
对于SNMPv2-Trap-PDU,不生成响应。
3.5. 代理转发器应用 (Proxy Forwarder Applications)
代理转发器应用在SNMP实体之间转发SNMP消息。代理转发器可以执行协议转换、安全转换或管理信息视图转换。
代理转发器应用执行两种类型的转发:
- 请求转发(Request Forwarding): 转发命令请求及其响应
- 通知转发(Notification Forwarding): 转发通知消息
3.5.1. 请求转发 (Request Forwarding)
当代理转发器接收到命令请求时:
-
消息处理子系统调用代理转发器的接收PDU原语,传递请求参数。
-
代理转发器使用SNMP-PROXY-MIB确定如何转发请求:
a. 查询snmpProxyTable,使用接收到的参数作为键:
- contextEngineID
- contextName
- 传输域和传输地址
- PDU类型
b. 如果找到匹配的条目,提取转发参数:
- 目标传输域和传输地址
- 目标消息处理模型
- 目标安全模型
- 目标安全名称
- 目标安全级别
- 目标contextEngineID
- 目标contextName
-
代理转发器可能需要修改PDU以适应目标SNMP版本。例如:
- SNMPv2到SNMPv1: 转换error-status代码
- SNMPv1到SNMPv2: 转换陷阱PDU格式
-
代理转发器调用消息处理子系统的发送PDU原语,将修改后的请求转发到目标。
-
当从目标接收到响应时:
a. 可能需要再次修改响应PDU以适应原始请求者的SNMP版本
b. 调用消息处理子系统的返回响应PDU原语,将响应转发回原始请求者
3.5.2. 通知转发 (Notification Forwarding)
当代理转发器接收到通知时:
-
消息处理子系统调用代理转发器的接收PDU原语,传递通知参数。
-
代理转发器使用SNMP-PROXY-MIB确定如何转发通知:
a. 查询snmpProxyTable,使用接收到的参数作为键
b. 如果找到匹配的条目,提取转发参数
-
代理转发器可能需要修改通知PDU:
- SNMPv1陷阱到SNMPv2陷阱: 转换PDU格式和variable-bindings
- SNMPv2陷阱到SNMPv1陷阱: 转换PDU格式
-
代理转发器调用消息处理子系统的发送PDU原语,将通知转发到目标。
-
如果原始通知是InformRequest-PDU且转发的通知也是InformRequest-PDU:
a. 等待来自目标的响应
b. 当接收到响应时,将响应转发回原始通知发起者
3.5.3. 代理转发器的特殊考虑 (Special Considerations for Proxy Forwarders)
代理转发器必须处理几种特殊情况:
-
PDU大小调整: 如果目标支持的最大消息大小小于原始请求,代理转发器可能需要返回tooBig错误或拆分请求。
-
上下文转换: 代理转发器可能需要在不同的contextEngineID和contextName之间进行映射。
-
访问控制: 代理转发器除了目标命令响应器的访问控制之外,还应用自己的访问控制策略。
-
错误映射: 在SNMP版本之间转换时,可能需要映射错误代码。例如,SNMPv2的noAccess错误可能需要映射到SNMPv1中的genErr。
-
超时和重试: 代理转发器可能需要为转发的请求实现自己的超时和重试机制,独立于原始请求者的超时。
-
通知过滤: 对于通知转发,代理转发器可以应用过滤规则,以选择性地转发特定类型的通知。