查看源代码 代理功能描述

SNMP 代理系统由一个主代理和可选的子代理组成。

该工具可以轻松地在运行时动态扩展 SNMP 代理。MIB 可以随时加载和卸载。也可以在运行时轻松更改 MIB 的实现,而无需重新编译 MIB。MIB 实现与代理程序明显分离。

为了方便 MIB 的增量实现,该工具可以为整个 MIB 或其部分生成原型实现。这允许同时开发不同的 MIB 和管理应用程序。

功能

要实现代理,程序员需要为代理将要支持的 MIB 中的变量和表编写检测函数。无需任何编程即可创建处理 setgetget-next 的运行原型。

该工具包提供以下功能:

  • 多语言、多线程、可扩展的 SNMP 代理
  • 使用高级编程语言轻松编写检测函数
  • 基本故障处理,例如自动类型检查
  • 访问控制
  • 身份验证
  • 通过加密实现隐私
  • 在运行时加载和卸载 MIB
  • 无需重新编译 MIB 即可更改检测函数的能力
  • 快速原型环境,其中 MIB 编译器可以使用通用检测函数,稍后可由程序员进行改进
  • 用于处理事务和检查 set 请求一致性的简单且可扩展的模型
  • 通过分布式 Erlang 支持子代理概念
  • 用于发送通知(陷阱和通知)的机制
  • 支持在 Mnesia DBMS 中实现 SNMP 表。

SNMPv1、SNMPv2 和 SNMPv3

SNMP 开发工具包适用于所有三个版本的标准 Internet 管理框架:SNMPv1、SNMPv2 和 SNMPv3。它们都共享相同的基本结构和组件,并且遵循相同的架构。

这些版本在以下 RFC 中定义:

  • SNMPv1 RFC 1555、1157 1212、1213 和 1215
  • SNMPv2 RFC 1902 - 1907
  • SNMPv3 RFC 2570 - 2575

随着时间的推移,随着框架从 SNMPv1、通过 SNMPv2 发展到 SNMPv3,每个架构组件的定义都变得更加丰富和明确,但基本架构保持一致。

与 SNMPv1 相比,SNMPv2 的主要特点是:

  • get-bulk 操作,用于传输大量数据。
  • 增强的错误代码。
  • 用于 MIB 规范的更精确的语言

定义 SNMPv2 的标准文档是不完整的,因为它们没有指定 SNMPv2 消息的外观。消息格式和安全问题留给特殊的管理框架处理。其中一个框架是基于社区的 SNMPv2 框架 (SNMPv2c),它使用与 SNMPv1 相同的消息格式和框架。还存在其他实验性框架,例如 SNMPv2u 和 SNMPv2*。

SNMPv3 规范采用模块化方法来处理 SNMP。所有模块都相互分离,可以单独扩展或替换。模块示例包括消息定义、安全性和访问控制。SNMPv3 的主要特点是:

  • 添加了加密和身份验证。
  • 定义了代理配置的 MIB。

所有这些规范通常被称为“SNMPv3”,但实际上只有消息模块(定义了新的消息格式)和安全模块(负责加密和身份验证)不能与 SNMPv1 或 SNMPv2c 一起使用。在此版本的代理工具包中,使用了所有用于代理配置的标准 MIB。这包括用于定义通知的管理目标的 MIB。无论代理配置为使用哪个 SNMP 版本,都将使用这些 MIB。

此工具包中的可扩展代理理解 SNMPv1、SNMPv2c 和 SNMPv3。回想一下,SNMP 由两个独立的部分组成,即 MIB 定义语言 (SMI) 和协议。在协议级别,代理可以配置为同时使用 v1、v2c、v3 或它们的任意组合,即 v1 请求获得 v1 答复,v2c 请求获得 v2c 答复,v3 请求获得 v3 答复。在 MIB 级别,MIB 编译器可以编译 SMIv1 和 SMIv2 MIB。一旦编译完成,任何格式都可以加载到代理中,而无需考虑代理配置为使用哪个协议版本。这意味着代理将 v2 通知转换为 v1 陷阱,反之亦然。例如,可以将 v2 MIB 加载到仅使用 v1 的代理中。RFC 1908 和 RFC 2089 中描述了两种协议之间转换的步骤。

为了使实现能够充分利用增强的 SNMPv2 错误代码,在发生错误的情况下,检测函数必须始终返回 SNMPv2 错误代码。如有必要,代理会将这些错误代码转换为相应的 SNMPv1 错误代码。

注意

从 SMIv1 MIB 到 SNMPv2c 或 SNMPv3 答复的转换始终非常直接,但是从 v2 MIB 到 v1 答复的转换稍微复杂一些。SMIv2 中有一种称为 Counter64 的数据类型,SNMPv1 管理器无法正确解码。因此,代理永远不能向 SNMPv1 管理器发送 Counter64 对象。在这些情况下,常见的做法是在向 SNMPv1 管理器发送答复或陷阱时,简单地忽略任何 Counter64 对象。例如,如果 SNMPv1 管理器尝试 GET 类型为 Counter64 的对象,它将收到 noSuchName 错误,而 SNMPv2 管理器将获得正确的值。

操作

要获得运行中的代理,需要执行以下步骤:

  1. 在文本文件中以 SMI 编写 MIB。
  2. 在 Erlang 中编写检测函数并进行编译。
  3. 将其名称放在关联文件中。
  4. 通过 MIB 编译器运行 MIB 和关联文件。
  5. 配置应用程序(代理)。
  6. 启动应用程序(代理)。
  7. 将编译的 MIB 加载到代理中。

本节中的图说明了 SNMP 代理的开发步骤。

MIB Compiler Principles

编译器会解析 SMI 文件,并将每个表或变量与一个检测函数关联起来(请参见图 MIB 编译器原理)。MIB 编译时不需要实际的检测函数,只需要它们的名称。

编译器生成的二进制输出文件由代理在 MIB 加载时读取(请参见图 启动代理)。检测是普通的 Erlang 代码,它在第一次调用时显式或自动加载。

Starting the Agent

SNMP 代理系统由一个主代理和可选的子代理组成。主代理可以看作是一种特殊的子代理。它实现核心代理功能、UDP 数据包处理、类型检查、访问控制、陷阱分发等。从用户角度来看,它被用作普通的子代理。

如果您的应用程序需要 SNMP 工具包的特殊分布式支持,则只需要子代理。如果应用程序需要比主代理中更复杂的 set 事务方案,也可以使用子代理。

以下图示显示了运行时系统中可能的样子。

Architecture

一个典型的操作可能包括以下步骤:

  1. 管理器向代理发送请求。
  2. 主代理解码传入的 UDP 数据包。
  3. 主代理确定应在此处处理请求中的哪些项,以及应转发到其子代理的哪些项。
  4. 所有子代理重复步骤 3。
  5. 每个子代理都调用其已加载 MIB 的检测。
  6. 调用检测的结果会传播回主代理。
  7. 请求的答案被编码为 UDP 协议数据单元 (PDU)。

显示的步骤顺序可能比正常情况更复杂,但它说明了可用的功能量。应注意以下几点:

  • 一个代理可以同时加载多个 MIB。
  • 子代理也可以有子代理。每个子代理都可以注册任意数量的子子代理,形成一个层次结构。
  • 一个 MIB 可以与多个应用程序通信。
  • 检测可以使用分布式 Erlang 与应用程序通信。

大多数应用程序只需要主代理,因为一个代理可以同时加载多个 MIB。

子代理和 MIB 加载

由于应用程序往往是瞬态的(它们是动态加载和卸载的),因此这些应用程序的管理也必须是动态的。例如,如果我们有一个用于机架的设备 MIB 和用于可以安装在机架中的板的不同 MIB,则应该在插入卡时加载卡的 MIB,并在移除卡时卸载。

在此代理系统中,有两种动态安装管理信息的方式。最常见的方法是将 MIB 加载到代理中。另一种方法是使用子代理,该子代理由应用程序控制,并且能够注册和取消注册自身。子代理可以注册自己来管理子树(不要与 erlang:register 混淆)。子树由对象标识符标识。注册子代理后,它会接收对该特定子树的所有请求,并且负责答复它们。还应注意,子代理可以随时启动和停止。

与其他 SNMP 代理包相比,这种使用子代理的方式存在显着差异。其他包通常使用子代理在运行时加载和卸载 MIB。在 Erlang 中,可以轻松地在运行时加载代码,并且可以将 MIB 加载到现有子代理中。不需要创建新进程来处理新的 MIB。

使用子代理的原因如下:

  • 提供比主代理更复杂的 set 事务方案
  • 避免不必要的进程通信
  • 提供一种更轻量级的机制,用于在运行时加载和卸载 MIB
  • 提供与其他 SNMP 代理工具包的交互。

有关这些主题的更多信息,请参阅本用户指南中的高级代理主题章节。

子代理之间的通信协议是分布式 Erlang 系统中使用的常规消息传递。这意味着与其他协议(如 SMUX、DPI、AgentX 和类似协议)相比,子代理通信非常高效。

上下文和团体

上下文是 SNMP 实体可访问的管理信息的集合。一个管理对象的实例可以存在于多个上下文中。一个 SNMP 实体可能可以访问多个上下文。

每个被管理对象可以在一个 SNMP 实体中存在多个实例。为了识别由 MIB 模块指定的实例,需要一种方法通过其“作用域”或上下文来区分实际实例。通常,上下文是物理设备或逻辑设备。它可以包含多个设备、单个设备的子集或多个设备的子集,但上下文始终被定义为单个 SNMP 实体的子集。为了能够识别 SNMP 实体中的特定管理信息项,必须使用上下文、对象类型及其实例。

例如,来自 RFC1573 的被管理对象类型 ifDescr 被定义为网络接口的描述。要识别设备 X 的第一个网络接口的描述,需要四个信息:提供对设备 X 的管理信息访问的 SNMP 实体的 snmpEngineID,contextName(设备 X),被管理对象类型 (ifDescr),以及实例 ("1")。

在 SNMPv1 和 SNMPv2c 中,消息中的团体字符串被用于(至少)三个不同的目的

  • 标识上下文
  • 提供身份验证
  • 标识一组陷阱目标

在 SNMPv3 中,这些使用领域中的每一个都有其自己独特的机制。上下文由 SNMP 实体的名称 contextEngineID 和上下文的名称 contextName 标识。每个 SNMPv3 消息都包含这两个参数的值。

有一个 MIB,SNMP-COMMUNITY-MIB,它将团体字符串映射到 contextEngineIDcontextName。因此,每个消息,无论 SNMPv1、SNMPv2c 还是 SNMPv3 消息,都始终唯一地标识一个上下文。

对于代理,接收到的消息标识的 contextEngineID 始终等于代理的 snmpEngineID。否则,该消息并非旨在发送给该代理。如果代理配置了多个上下文,则检测代码必须能够确定请求是针对哪个上下文的。为此目的提供了函数 snmpa:current_context/0

默认情况下,代理除了默认上下文 "" 之外,不了解任何其他上下文。如果要支持更多上下文,必须使用适当的配置文件 代理配置文件 显式添加这些上下文。

代理的管理

有一组标准 MIB,用于控制和配置 SNMP 代理。所有这些 MIB,除了可选的 SNMP-PROXY-MIB(仅用于代理代理)之外,都在此代理中实现。此外,可以配置实际加载哪些 MIB,从而使 SNMP 管理器可见。例如,在不安全的环境中,最好不要使定义访问控制的 MIB 可见。请注意,即使未加载 MIB,MIB 定义的数据也会在代理内部使用。本章描述了这些标准 MIB 及其实现的一些方面。

任何 SNMP 代理都必须实现 MIB-II 中定义的 system 组和 snmp 组。这些组的定义从 SNMPv1 更改为 SNMPv2。该发行版提供了这两个版本的 MIB 和实现。SNMPv1 的 MIB 文件名为 STANDARD-MIB,对应的 SNMPv2 的 MIB 文件名为 SNMPv2-MIB。如果代理仅配置为 SNMPv1,则默认加载 STANDARD-MIB;否则,默认加载 SNMPv2-MIB。可以通过显式加载此 MIB 的另一个版本来覆盖此默认行为,例如,可以选择实现这两个 MIB 中所有对象的并集。

SNMPv3 代理必须实现 SNMP-FRAMEWORK-MIB 和 SNMP-MPD-MIB。如果代理配置为 SNMPv3,则默认加载这些 MIB。也可以为其他版本加载这些 MIB。

还有其他五个标准 MIB,也可以加载到代理中。这些 MIB 是

  • SNMP-TARGET-MIB 和 SNMP-NOTIFICATION-MIB,定义用于配置管理目标(即通知(陷阱和信息)的接收者)的管理对象。这些 MIB 可以与任何 SNMP 版本一起使用。
  • SNMP-VIEW-BASED-ACM-MIB,定义用于访问控制的管理对象。此 MIB 可以与任何 SNMP 版本一起使用。
  • SNMP-COMMUNITY-MIB,定义用于 SNMPv1 和 SNMPv2c 与 SNMPv3 共存的管理对象。仅当使用 SNMPv1 或 SNMPv2c 时(可能与 SNMPv3 结合使用)此 MIB 才有用。
  • SNMP-USER-BASED-SM-MIB,定义用于身份验证和隐私的管理对象。此 MIB 仅适用于 SNMPv3。

所有这些 MIB 都应加载到主代理中。加载后,这些 MIB 始终在所有上下文中可用。

发行版中提供了它们的 ASN.1 代码、Erlang 源代码和生成的 .hrl 文件,分别位于 snmp 应用程序中的目录 mibssrcinclude 中。

.hrl 文件是使用 snmpc:mib_to_hrl/1 生成的。在您的代码中包含这些文件,如下例所示

-include_lib("snmp/include/SNMPv2-MIB.hrl").

这些表中定义的被管理对象的初始值在启动时从一组配置文件中读取。这些在 配置文件 中描述。

STANDARD-MIB 和 SNMPv2-MIB

这些 MIB 包含 RFC1213 (STANDARD-MIB) 或 RFC1907 (SNMPv2-MIB) 中定义的 MIB-II 中的 snmp-system 组。它们在 snmp_standard_mib 模块中实现。snmp 计数器都驻留在易失性内存中,而 systemsnmpEnableAuthenTraps 变量驻留在持久性内存中,使用 SNMP 内置数据库(有关更多详细信息,请参阅参考手册,snmp 部分,snmpa_local_db 模块)。

如果需要任何这些变量的另一种实现(例如,将持久性变量存储在 Mnesia 数据库中),则必须制作变量的自己的实现。该 MIB 将被编译和加载,而不是默认 MIB。新的已编译 MIB 必须与原始 MIB 具有相同的名称(即 STANDARD-MIB 或 SNMPv2-MIB),并且位于 SNMP 配置目录中(请参阅 配置文件)。

始终加载这些 MIB 中的一个。如果仅使用 SNMPv1,则加载 STANDARD-MIB,否则加载 SNMPv2-MIB。

数据类型

SNMPv2 中有一些新的数据类型,在 SNMPv1 中也很有用。在 STANDARD-MIB 中,定义了三种数据类型,RowStatusTruthValueDateAndTime。这些数据类型最初在 SNMPv2-TC (RFC1903) 中定义为文本约定。

SNMP-FRAMEWORK-MIB 和 SNMP-MPD-MIB

SNMP-FRAMEWORK-MIB 和 SNMP-MPD-MIB 定义了额外的只读管理对象,这些对象在 RFC2271 中定义的通用 SNMP 框架以及 RFC2272 中定义的通用消息处理和调度模块中使用。它们是通用的,因为它们不与任何特定的 SNMP 版本绑定。

这些 MIB 中的对象分别在模块 snmp_framework_mibsnmp_standard_mib 中实现。所有对象都驻留在易失性内存中,并且在启动时始终重新读取配置文件。

如果使用 SNMPv3,则默认加载这些 MIB。

SNMP-TARGET-MIB 和 SNMP-NOTIFICATION-MIB

SNMP-TARGET-MIB 和 SNMP-NOTIFICATION-MIB 定义了用于配置通知接收者的管理对象。它们在 RFC2273 中详细描述。此处仅给出简要描述。

这些 MIB 中的所有表都有一个 StorageType 类型的列。此列的值指定如何存储每一行,以及在代理重新启动时会发生什么。该实现支持值 volatilenonVolatile。当最初使用配置文件中的数据填充表格时,这些行将自动具有存储类型 nonVolatile。如果代理重新启动,则所有 nonVolatile 行都会在重新启动后幸存下来,而 volatile 行会丢失。默认情况下,不会在重新启动时读取配置文件。

默认情况下不加载这些 MIB。

snmpNotifyTable

snmpNotifyTable 中的条目选择一组管理目标,这些目标应接收通知,以及应发送给每个选定管理目标的通知类型(陷阱或信息)。当应用程序使用函数 send_notification/5 或函数 send_trap 发送通知时,调用中指定的参数 NotifyName 用作表格中的索引。通知将发送到该条目选择的管理目标。

snmpTargetAddrTable

snmpTargetAddrTable 中的条目定义每个管理目标的传输参数(例如 IP 地址和 UDP 端口)。snmpNotifyTable 中的每一行都可能引用 snmpTargetAddrTable 中的许多行。snmpTargetAddrTable 中的每一行都引用 snmpTargetParamsTable 中的一个条目。

snmpTargetParamsTable

snmpTargetParamsTable 中的条目定义要使用的 SNMP 版本,以及要使用的安全参数。

要使用的 SNMP 版本由指定消息处理模型隐式定义。此版本的代理处理 v1v2cv3 模型。

每一行都指定要使用的安全模型,以及安全级别和安全参数。

SNMP-VIEW-BASED-ACM-MIB

SNMP-VIEW-BASED-ACM-MIB 定义了用于控制管理器访问被管理对象的管理对象。基于视图的访问控制模块 (VACM) 可以与任何 SNMP 版本一起使用。但是,如果它与 SNMPv1 或 SNMPv2c 一起使用,则 SNMP-COMMUNITY-MIB 定义了额外的对象,用于将团体字符串映射到 VACM 参数。

此 MIB 中的所有表都具有 StorageType 类型的列。此列的值指定每一行的存储方式,以及代理重新启动时会发生什么。该实现支持 volatilenonVolatile 值。当表最初从配置文件中填充数据时,这些行的存储类型将自动为 nonVolatile。如果代理重新启动,所有 nonVolatile 行将在重新启动后保留,而 volatile 行将丢失。默认情况下,配置文件在重新启动时不会读取。

默认情况下,此 MIB 不会加载。

RFC2275 中详细描述了 VACM。此处仅提供简要说明。

基本概念是MIB 视图。MIB 视图是代理实现的所有对象的子集。管理器可以访问特定的 MIB 视图,具体取决于所使用的安全参数、请求所在的上下文以及所发出的请求类型。

下图概述了选择 MIB 视图的机制

Overview of the mechanism of MIB selection

vacmContextTable

vacmContextTable 是一个只读表,其中列出了所有可用的上下文。

vacmSecurityToGroupTable

vacmSecurityToGroupTablesecurityModelsecurityName 映射到 groupName

vacmAccessTable

vacmAccessTablegroupName(在 vacmSecurityToGroupTable 中找到)、contextNamesecurityModelsecurityLevel 映射到每种操作类型(读取、写入或通知)的 MIB 视图。MIB 视图表示为 viewNameviewName 表示的 MIB 视图的定义在 vacmViewTreeFamilyTable 中找到

vacmViewTreeFamilyTable

vacmViewTreeFamilyTableviewName 索引,并定义 MIB 视图中包含哪些对象。

该表的 MIB 定义如下

VacmViewTreeFamilyEntry ::= SEQUENCE
    {
        vacmViewTreeFamilyViewName     SnmpAdminString,
        vacmViewTreeFamilySubtree      OBJECT IDENTIFIER,
        vacmViewTreeFamilyMask         OCTET STRING,
        vacmViewTreeFamilyType         INTEGER,
        vacmViewTreeFamilyStorageType  StorageType,
        vacmViewTreeFamilyStatus       RowStatus
    }

INDEX { vacmViewTreeFamilyViewName,
        vacmViewTreeFamilySubtree
      }

每个 vacmViewTreeFamilyViewName 都引用子树的集合。

MIB 视图语义

MIB 视图是包含和排除的子树的集合。子树由 OBJECT IDENTIFIER 标识。每个子树都关联一个掩码。

对于每个可能的 MIB 对象实例,如果满足以下条件,则该实例属于子树

  • 该 MIB 对象实例的 OBJECT IDENTIFIER 名称包含的子标识符至少与子树一样多,并且
  • 只要关联掩码的相应位为 1(0 是匹配任何内容的通配符),则该 MIB 对象实例名称中的每个子标识符都与子树的相应子标识符匹配。

MIB 视图中对象实例的成员资格由以下算法确定

  • 如果 MIB 对象实例不属于任何相关的子树,则该实例不在 MIB 视图中。
  • 如果 MIB 对象实例恰好属于一个子树,则根据该条目的类型,该实例包含在相关 MIB 视图中或从相关 MIB 视图中排除。
  • 如果 MIB 对象实例属于多个子树,则使用包含最多子标识符且字典顺序最大的子树。

注意

如果 OBJECT IDENTIFIER 比 MIB 中对象类型的 OBJECT IDENTIFIER 长,则它引用对象实例。因此,可以控制是否应显示表中特定的行。

SNMP-COMMUNITY-MIB

SNMP-COMMUNITY-MIB 定义了用于 SNMPv1 和 SNMPv2c 与 SNMPv3 共存的管理对象。具体来说,它包含用于在团体字符串和与版本无关的 SNMP 消息参数之间进行映射的对象。此外,此 MIB 提供了一种机制,用于对传入请求执行源地址验证,以及根据传出通知的目标地址选择团体字符串。

此 MIB 中的所有表都具有 StorageType 类型的列。此列的值指定每一行的存储方式,以及代理重新启动时会发生什么。该实现支持 volatilenonVolatile 值。当表最初从配置文件中填充数据时,这些行的存储类型将自动为 nonVolatile。如果代理重新启动,所有 nonVolatile 行将在重新启动后保留,而 volatile 行将丢失。默认情况下,配置文件在重新启动时不会读取。

默认情况下,此 MIB 不会加载。

SNMP-USER-BASED-SM-MIB

SNMP-USER-BASED-SM-MIB 定义了用于基于用户的安全模型的管理对象。

此 MIB 中的所有表都具有 StorageType 类型的列。此列的值指定每一行的存储方式,以及代理重新启动时会发生什么。该实现支持 volatilenonVolatile 值。当表最初从配置文件中填充数据时,这些行的存储类型将自动为 nonVolatile。如果代理重新启动,所有 nonVolatile 行将在重新启动后保留,而 volatile 行将丢失。默认情况下,配置文件在重新启动时不会读取。

默认情况下,此 MIB 不会加载。

OTP-SNMPEA-MIB

OTP-SNMPEA-MIB 在代理的早期版本中使用,那时还没有用于访问控制、MIB 视图和陷阱目标规范的标准 MIB。此 MIB 中的所有对象现在都已过时。

通知

通知在 SMIv1 中使用 MIB 定义中的 TRAP-TYPE 宏定义(请参阅 RFC1215)。SMIv2 中对应的宏是 NOTIFICATION-TYPE。当应用程序决定发送通知时,它会调用以下函数之一

snmpa:send_notification(Agent, Notification, Receiver
                       [, NotifyName, ContextName, Varbinds])
snmpa:send_trap(Agent, Notification, Community [, Receiver, Varbinds])

提供加载了定义通知的 MIB 的代理的注册名称或进程标识符以及通知的符号名称。

如果使用 send_notification/3,4 函数,则会选择 RFC2273 中定义的所有管理目标。Receiver 参数定义代理应在何处发送有关 inform 请求传递的信息。

如果使用 send_notification/5 函数,则必须提供 NotifyName。此参数用作 snmpNotifyTable 中的索引,并使用该单个条目定义的管理目标。

send_notification/6 函数是该函数的最通用版本。必须指定一个 ContextName,从中发送通知。如果未指定此参数,则使用默认上下文 ("")。

保留函数 send_trap 是为了向后兼容,不应在新代码中使用。使用此函数的应用程序将继续工作。当发送通知时,代理使用 snmpNotifyName 作为团体字符串。

通知发送

发送通知的最简单方法是调用函数 snmpa:send_notification(Agent, Notification, no_receiver)。在这种情况下,代理执行 get 操作以检索通知规范(使用 TRAP-TYPE 或 NOTIFICATION-TYPE 宏)中定义的对象值。该通知会发送到目标和通知表中定义的所有管理器,要么作为未确认的陷阱发送,要么作为已确认的 inform 请求发送。

如果函数的调用者想知道是否收到了特定通知的确认(前提是它作为 inform 发送),则可以将 Receiver 参数指定为 {Tag, ProcessName}(有关更多详细信息,请参阅参考手册的 snmp 部分、模块 snmp)。在这种情况下,代理会为每个管理目标发送消息 {snmp_notification, Tag, {got_response, ManagerAddr}}{snmp_notification, Tag, {no_response, ManagerAddr}}

有时,无法通过 get 操作检索通知规范中某些对象的值。但是,当调用 send_notification 函数时,这些值是已知的。如果对象是表中的元素,则会发生这种情况。可以将某些对象的值提供给 send_notification 函数 snmpa:send_notification(Agent, Notification, Receiver, Varbinds)。在此函数中,VarbindsVarbind 的列表,其中每个 Varbind 都是以下之一:

  • {Variable, Value},其中 Variable 是通知规范中引用的标量变量的符号名称。
  • {Column, RowIndex, Value},其中 Column 是列变量的符号名称。RowIndex 是指定元素的索引列表。如果是这种情况,则在陷阱中发送的 OBJECT IDENTIFIER 是附加到表列的 OBJECT IDENTIFIER 的 RowIndex。这是指定元素的 OBJECT IDENTIFIER。
  • {OID, Value},其中 OID 是对象实例、标量变量或列变量的 OBJECT IDENTIFIER。

例如,要在通知中指定 sysLocation 应具有值 "upstairs",我们可以使用以下之一:

  • {sysLocation, "upstairs"}
  • {[1,3,6,1,2,1,1,6,0], "upstairs"}

还可以指定应该在通知中发送但未在通知规范中定义的额外变量的名称和值。

通知将发送到表中找到的所有管理目标。但是,请确保每个管理器都可以访问通知中的变量。如果变量在管理器的 MIB 视图之外,则该管理器将不会收到通知。

注意

根据定义,不可能在通知中发送 ACCESS 为 not-accessible 的对象。但是,历史上通常这样做,因此我们允许在发送通知时这样做。如果变量的 ACCESS 为 not-accessible,则用户必须在 Varbinds 列表中为该变量提供值。代理无法执行 get 操作来检索此值。

通知筛选器

可以向代理添加通知筛选器。当要发送通知时,将调用这些筛选器。它们的目的是允许修改、抑制或其他类型的操作。

通知过滤器是一个实现 snmpa_notification_filter 行为的模块。可以使用以下函数添加/删除过滤器:snmpa:register_notification_filter/5snmpa:unregister_notification_filter/2

除非另有说明,已注册过滤器的顺序将是它们注册的顺序。

子代理路径

如果未向 send_notification 函数提供对象的值,则子代理将执行 get 操作来检索它。如果此子代理中未实现该对象,则其父代理会尝试执行 get 操作来检索它。如果此代理中也没有实现该对象,则它会将其转发给其父代理,依此类推。最终会到达主代理,此时必须解析所有未知对象值。如果即使主代理也不知道某个对象,则将其视为错误,并通过调用错误报告模块的 user_err/2 来报告。在这种情况下,不会发送任何通知。

对于给定的通知,通知规范中引用的变量必须由加载了 MIB 的代理或该代理的某个父代理来实现。如果不是,则应用程序必须为未知变量提供值。应用程序还必须为表中的所有元素提供值。

发现

对于包含期望响应的有效负载的消息(例如 SNMPv2-Trap、Response 或 Report PDU),发送者权威的

对于包含期望响应的有效负载的消息(例如 Get、GetNext、Get-Bulk、Set 或 Inform PDU),接收者权威的

代理可以执行和响应发现。

代理自主响应发现,无需用户交互。

通过调用 snmpa:discovery/6 函数来启动对管理器的发现。 target_addr.conf 文件中目标(管理器)条目的 EngineId 字段的值必须为 discovery。请注意,如果管理器没有响应,则 TimeoutRetryCount 字段会决定该函数在返回之前将挂起多长时间。

一次只能对一个管理器执行发现。