在线文档教程
Erlang 20

2.代理功能描述 | 2. Agent Functional Description

2 Agent功能描述

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

该工具使运行时动态扩展SNMP代理变得容易。MIB可以随时加载和卸载。在运行时更改MIB的实现也很容易,无需重新编译MIB。MIB的实现与代理显然是分开的。

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

2.1特征

为了实现代理,程序员为代理将支持的MIB中的变量和表写入检测函数。正在运行的原型,处理setget以及get-next无需任何编程创建。

该工具包提供以下内容:

  • 多语言多线程可扩展SNMP代理

  • 用高级程序设计语言轻松编写仪表功能。

  • 基本故障处理,如自动类型检查

  • 存取控制

  • 认证

  • 通过加密实现隐私

  • MIB在运行时的装卸

  • 能够在不重新编译MIB的情况下更改检测功能

  • 快速原型环境,MIB编译器可以使用通用的插装功能,稍后程序员可以对其进行改进。

  • 一种简单、可扩展的事务处理和集请求一致性检查模型

  • 通过分布式Erlang对子代理概念的支持

  • 发送通知的机制(陷阱和通知)

  • 支持在Mnesia DBMS中实现SNMP表。

2.2 SNMPv 1、SNMPv 2和SNMPv 3

SNMP开发工具包与标准Internet管理框架的所有三个版本(SNMPv 1、SNMPv 2和SNMPv 3)一起工作。它们都有着相同的基本结构和组件。它们遵循相同的架构。

版本在以下RFCS中定义:

  • SNMPv 1 RFC 1555,1157 1212,1213和1215

  • SNMPv 2 RFC 1902-1907

  • SNMPv 3 RFC 2570-2575

随着时间的推移,随着框架从SNMPv 1到SNMPv 2的发展,每个体系结构组件的定义都变得更加丰富和清晰,但基本的体系结构仍然是一致的。

与SNMPv 1相比,SNMPv 2的主要特点是:

  • get-bulk在传输大量数据的操作。

  • 增强错误码

  • 更精确的MIB规范语言

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

SNMPv 3规范对SNMP采用模块化方法。所有模块彼此分离,可以单独扩展或替换。模块的例子是消息定义、安全性和访问控制。SNMPv 3的主要特点是:

  • 增加了加密和身份验证。

  • 定义了用于代理配置的MIB。

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

该工具包中的可扩展代理理解SNMPv 1、SNMPv2c和SNMPv 3。回想一下SNMP由两个独立的部分组成,MIB定义语言%28SMI%29和协议。在协议级别上,代理可以被配置为同时讲v1、v2C、v3或它们的任何组合,即v1请求得到v1应答,V2C请求得到V2C应答,v3请求得到v3应答。在MIB级别上,MIB编译器可以同时编译SMIv 1和SMIv 2 MIB。编译后,任何格式都可以加载到代理中,而不管代理配置使用哪个协议版本。这意味着代理将从v2通知转换为v1陷阱,反之亦然。例如,v2MIB可以加载到只讲v1的代理中。RFC 1908和RFC 2089描述了这两种协议之间的转换过程。

为了充分利用增强型SNMPv 2错误码,在出现错误时,仪器功能必须始终返回SNMPv 2错误码。如果有必要,代理将这些代码转换为相应的SNMPv 1错误代码。

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

2.3 操作

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

  • 在文本文件中用SMI编写MIB。

  • 用Erlang编写工具函数并编译它们。

  • 把他们的名字放在关联文件中。

  • 通过MIB编译器与关联文件一起运行MIB。

  • 配置应用程序%28代理%29。

  • 启动应用程序(代理程序)。

  • 将编译的MIB加载到代理中。本节中的图表说明了开发SNMP代理所涉及的步骤。图2.1:MIB编译器原理编译器解析SMI文件,并将每个表或变量与仪表功能相关联(请参见图MIB Compiler Principles)。MIB编译时不需要实际的仪器功能,只需要它们的名称。代理程序在MIB加载时读取由编译器生成的二进制输出文件(请参见图Starting the Agent)。该工具是普通的Erlang代码,它在第一次调用时显式或自动加载。图2.2:启动代理SNMP代理系统由一个主代理和可选的子代理组成。主代理可以被看作是一种特殊的子代理。它实现了核心代理功能,UDP数据包处理,类型检查,访问控制,陷阱分配等。从用户角度来看,它被用作普通的子代理。只有您的应用程序需要特别支持从SNMP工具包进行分发时才需要子代理。如果应用程序需要比主代理程序更复杂的集合事务处理方案,则还可以使用子代理程序。下图显示了系统在运行时的外观。图2.3:

  • Manager向代理发送请求。

  • 主代理对传入的UDP数据包进行解码。

  • 主代理程序确定在请求中哪些项应该在这里处理,哪些项应该转发给其子代理。

  • 所有子代理都重复步骤3。

  • 每个子代理为其加载的MIB调用检测工具。

  • 调用工具的结果将传播回主代理。

  • 该请求的答案被编码为UDP协议数据单元(PDU)。

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

  • 代理可以同时加载多个MIB。

  • 子代理也可以有子代理。每个子代理可以有任意数量的子代理注册,形成层次结构.

  • 一个MIB可以与多个应用程序通信。

  • 工具可以使用分布式Erlang与应用程序进行通信。

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

2.4次代理与MIB装载

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

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

与其他SNMP代理包相比,这种使用子代理的方式有很大的不同。其他软件包通常使用子代理在运行时加载和卸载MIB.。在Erlang中,在运行时很容易加载代码,并且可以将MIB加载到现有的子代理中。没有必要为处理新的MIB创建一个新的流程。

使用子代理的原因如下:

  • 提供比主代理更复杂的集事务方案。

  • 避免不必要的进程通信

  • 为运行时装载和卸载mib提供更轻量级的机制。

  • 提供与其他SNMP代理工具包的交互。

Advanced Agent Topics有关这些主题的更多信息,请参阅本用户指南中的一章。

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

2.5背景与社区

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

每个被管理对象都可以存在于SNMP实体中的许多实例中。为了识别由MIB模块指定的实例,使用用于区分实际实例与其“范围”或上下文的方法。上下文通常是一个物理或逻辑设备。它可以包含多个设备,单个设备的子集或多个设备的子集,但上下文总是被定义为单个SNMP实体的子集。为了能够识别SNMP实体中特定的管理信息,必须使用上下文,对象类型及其实例。

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

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

  • 标识上下文

  • 提供身份验证

  • 识别一组陷阱目标在SNMPv3中,每个使用领域都有其独特的机制。上下文由SNMP实体contextEngineID的名称和上下文的名称来标识contextName。每个SNMPv3消息都包含这两个参数的值。有一个MIB,SNMP-COMMUNITY-MIB,它将社区字符串映射到contextEngineIDand contextName。因此,每条消息(SNMPv1,SNMPv2c或SNMPv3消息)总是唯一标识一个上下文。对于一个代理来说,contextEngineID由接收到的消息所标识的总是等于snmpEngineID该代理的。否则,该消息不适用于该代理。如果代理程序配置了多个上下文,那么检测代码必须能够找出请求所针对的上下文。有一个功能snmpa:current_context/0为此提供。默认情况下,代理不知道除默认上下文以外的任何其他上下文""。如果要支持更多上下文,则必须使用适当的配置文件明确添加这些上下文Agent Configuration Files。2.6 Agent的管理有一套标准的MIB,用于控制和配置SNMP Agent。除了可选的SNMP-PROXY-MIB(仅用于代理代理)之外,所有这些MIB均在此代理中实施。此外,可以配置这些MIB中的哪一个实际加载,从而使SNMP管理器可见。例如,在不安全的环境中,不要使MIB定义访问控制可见是个好主意。请注意,MIB定义的数据在代理内部使用,即使MIB未加载。本章介绍这些标准MIB及其实现的一些方面。任何SNMP代理都必须实现该system组和snmp组,在MIB-II中定义。这些组的定义已从SNMPv1更改为SNMPv2。这两个版本的MIB和实现都在发行版中提供。SNMPv1的MIB文件称为STANDARD-MIB,SNMPv2的对应称为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共存的管理对象。此MIB仅在使用SNMPv1或SNMPv2c时有用,可能与SNMPv3结合使用。

SNMP-USER-BASED-SM-MIB,它定义了用于认证和隐私的管理对象。此MIB仅在SNMPv3中有用。所有这些MIB都应该加载到主代理中。加载后,这些MIB始终可用于所有情况。 ASN.1代码,Erlang源代码以及为它们生成的.hrl文件在分发版中提供,并分别放置在snmp应用程序中的目录mibs,src和include中。 .hrl文件使用snmpc:mib_to_hrl / 1生成。将这些文件包含在代码中,如以下示例所示:-include_lib(“snmp / include / SNMPv2-MIB.hrl”)。

  • 该MIB对象实例的对象标识符名称至少包含与子树相同的子标识符,以及

  • 每当关联掩码的相应位为1(0是匹配任何内容的通配符)时,该MIB对象实例名称中的每个子标识符与子树的对应子标识符匹配。

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

  • 如果MIB对象实例不属于任何相关子树,则该实例不在MIB视图中。

  • 如果MIB对象实例恰好属于一个子树,则根据该条目的类型,该实例包含在相关的MIB视图中,或被排除在该子树中。

  • 如果一个MIB对象实例属于多个子树,则使用包含最大数量子标识符的子树,该子树在字典上是最大的。

如果对象标识符比MIB中对象类型的对象标识符长,则引用对象实例。因此,可以控制表中的特定行是否可见。

SNMP-COMMUNITY-MIB

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

此MIB中的所有表都有一个StorageType类型的列。 此列的值指定每行的存储方式,以及重新启动代理程序时发生的情况。 该实现支持volatile和nonVolatile的值。 当表最初由配置文件填充数据时,这些行将自动具有非易失性存储类型。 如果代理重新启动,则所有非易失性行都会在重新启动后存活,而易失性行将丢失。 缺省情况下,配置文件在重新启动时不会被读取。

默认情况下不加载此MIB。

SNMP-USER-BASED-SM-MIB

基于SNMP的SM-MIB定义了用于基于用户的安全模型的托管对象.

此MIB中的所有表都有一个StorageType类型的列。 该列的值指定每行的存储方式,以及重新启动代理程序时会发生的情况。 该实现支持volatile和nonVolatile的值。 当表最初由配置文件填充数据时,这些行将自动具有非易失性存储类型。 如果代理重新启动,则所有非易失性行都会在重新启动后存活,而易失性行将丢失。 缺省情况下,配置文件在重新启动时不会被读取。

默认情况下不加载此MIB。

OTP-SNMPEA-MIB

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

2.7 通知

通知在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参数定义了代理应该发送关于传送通知请求信息的位置。

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

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

该功能send_trap保持向后兼容性,不应在新代码中使用。使用此功能的应用程序将继续工作。snmpNotifyName代理在发送通知时将其用作社区字符串。

通知发送

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

如果函数的调用者想要知道是否收到确认通知(如果它是作为通知发送的),则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)。 在这个函数中,Varbinds是Varbind的列表,其中每个Varbind都是以下之一:

  • {Variable, Value},其中Variable是通知规范中引用的标量变量的符号名称。

  • {Column, RowIndex, Value},其中Column是列变量的符号名称。RowIndex是指定元素的索引列表。如果是这种情况,在陷阱中发送的OBJECT IDENTIFIER被RowIndex附加到表列的OBJECT IDENTIFIER中。这是指定元素的OBJECT IDENTIFIER。

  • {OID, Value},其中OID是对象的实例,标量变量或列变量的OBJECT IDENTIFIER 。

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

  • {sysLocation, "upstairs"}

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

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

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

根据定义,not-accessible在通知中不可能使用ACCESS发送对象。但是,历史上这通常是完成的,因此我们允许它发送通知。如果一个变量具有ACCESS not-accessible,那么用户必须为Varbinds列表中的变量提供一个值。代理不可能执行获取操作来检索此值。

通知过滤器

可以添加通知过滤器找个探员。在发送通知时将调用这些筛选器。它们的目的是允许修改、抑制或其他类型的行动。

通知过滤器是实现该snmpa_notification_filter行为的模块。使用以下功能添加/删除过滤器:snmpa:register_notification_filtersnmpa:unregister_notification_filter

除非另有规定,注册过滤器的顺序将是它们的注册顺序。

子代理路径

如果对象没有赋值给该send_notification函数,那么子代理将执行一个get操作来检索它。如果该子对象未在此子代理中实现,则其父代理将尝试执行获取操作以检索它。如果对象未在此代理中实现,则它将该对象转发给其父代,等等。最终到达主代理,并且此时所有未知的对象值必须被解析。如果某个对象甚至对于主代理都是未知的,则这被视为错误并且user_err/2通过对错误报告模块的调用来报告。在这种情况下,不会发送通知。

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

2.8 发现

发送者权威对于含有有效载荷,其消息期望(例如的SNMPv2-陷阱,响应或报告PDU)的响应。

所述接收器权威对于含有有效载荷,其期望的响应(例如获取,的GetNext,取块,设置或通知PDU)的消息。

代理既可以执行发现,也可以响应发现。

代理自动响应发现,不需要用户的交互。

通过调用发现功能来完成对管理者的发现。 target_addr.conf文件中目标(管理器)条目的EngineId字段必须具有值发现。 请注意,如果管理器没有响应,则Timeout和RetryCount字段将决定函数在返回之前将挂起多长时间。

发现只能针对一位管理者进行。