我这次是使用net-snmp软件开发包尝试开发SNMP客户端代理。Net-snmp是个开源软件,基于C语言开发,便于移植,用于开发snmp代理,但也提供管理端的查询工具。

首先得安装net-snmp这个软件。从网上可以下载相关的软件包,我在这里使用的是5.4.1版本。安装比较简单,先是要配置,然后编译,最后安装。也就是常规的configure, make ,make install三个步骤就可成功编译安装源代码。
运行net-snmp之前先要进行环境设置,否则无法查询到结果。环境配置文件由snmpconf命令交互生成。运行snmpconf后,提示有三个配置文件:snmpd.conf,snmptraps.conf,snmp.conf。其中,snmpd.conf用来配置代理和管理端通信时的参数,只需设置两个参数就可正常运行程序了,一是community name,有只读rocommunity和读写rwcommunity之分,相当于访问账号,这里设rocommunity为public;另一个是访问端口,设为snmp协议默认的161端口。 Snmp.conf是与mib库设置相关的配置文件。Snmptraps.conf用来设置代理陷阱。生成的配置文件snmpd.conf按照提示拷贝到/usr/local/share/snmp目录下。
当环境配置好了以后,运行snmpd,即snmp代理进程,就可以使用管理工具查询其中的信息了。Snmp的查询工具比较多,可以随便使用如snmpget,snmptranslate等来测试一下能否查询到代理里面mib的节点的值或者OID号。下面介绍一下什么是MIB。
MIB是Management Information Base的缩写,中文名字叫“管理信息库”,它是网络管理数据的标准,在这个标准里规定了网络代理设备必须保存的数据项目,数据类型,以及允许在每个数据项目中的操作。通过对这些数据项目的存取访问,就可以得到该网关的所有统计内容。再通过对多个网关统计内容的综合分析即可实现基本的网络管理。MIB的主要用途是让SNMP通过查讯代理MIB中相应对象的值,实现对对网络设备状态的监视。
MIB库简单的说就是一个树状的数据库,通过客户端软件,可以直接对树的节点进行查询,修改,增加,删除的操作。而我今天要说的就是如何在客户端代理里面,自定义MIB,也就是增加自己私有的MIB。
第一步,要写自己的MIB文件,定义节点的OID,数据类型,访问权限,值,描述信息等。举个例子来说明。下面是RFC1212中关键组件:
IMPORTS
ObjectName
FROM RFC1155-SMI
DisplayString
FROM RFC1158-MIB;
OBJECT-TYPE MACRO ::=
BEGIN
TYPE NOTATION ::=
-- must conform to
-- RFC1155's ObjectSyntax
"SYNTAX" type(ObjectSyntax)
"ACCESS" Access
"STATUS" Status
DescrPart
ReferPart
IndexPart
DefValPart
VALUE NOTATION ::= value (VALUE ObjectName)
Access ::= "read-only"
| "read-write"
| "write-only"
| "not-accessible"
Status ::= "mandatory"
| "optional"
| "obsolete"
| "deprecated"
DescrPart ::=
"DESCRIPTION" value (description DisplayString)
| empty
ReferPart ::=
"REFERENCE" value (reference DisplayString)
| empty
IndexPart ::=
"INDEX" "{" IndexTypes "}" | empty
                    IndexTypes ::=
IndexType | IndexTypes "," IndexType
IndexType ::=
-- if indexobject, use the SYNTAX
-- value of the correspondent
-- OBJECT-TYPE invocation
value (indexobject ObjectName)
-- otherwise use named SMI type
-- must conform to IndexSyntax below
| type (indextype)
DefValPart ::=
"DEFVAL" "{" value (defvalue ObjectSyntax) "}"
| empty
END
      SYNTAX:对象类型的抽象语法。
ACCESS:定义通过SNMP或其他协议访问对象实例的方法。访问子句规定该对象类型所需要的最低级别的支持。在具体实现中可以增加或限制访问,选项有只读、读写、只写和不可访问。在最后一种情况下,不能读取对象的取值,也不能设置对象的取值。
STATUS:指明该对象所需要的实现支持。支持可能是强制的或者可选的,对象也可以规定为替代的。替代对象必须被支持,但很有可能从下一个版本的MIB中被删除。最后,状态可以是废除的,表示管理系统不再实现该对象。
DescrPart:对象类型语义的文本描述。
ReferPart:在其他MIB模块中定义的文本交叉索引。
Indexpart:用于定义表。该子句只在对象类型符合概念行时出现。
DefValPart:定义可接受的默认值,代理在创建实例时使用。
VALUE NOTATION:规定用于通过SNMP访问该对象时使用的名称。
根据MIB文件的规格,写自己的MIB文件,我这里写的是一个叫MyMib.txt的文件,内容如下:
MyMib DEFINITIONS::=BEGIN
IMPORTS
enterprises,OBJECT-TYPE,Integer32,TimeTicks
FROM SNMPv2-SMI
TEXTUAL-CONVENTION, DisplayString FROM SNMPv2-TC;
internet OBJECT IDENTIFIER ::= { iso org(3) dod(6) 1 }
private OBJECT IDENTIFIER ::= { internet 4 }
enterprises OBJECT IDENTIFIER ::= { private 1 }
foxmail OBJECT IDENTIFIER::={enterprises 310}
SecondCounter OBJECT-TYPE
SYNTAX Integer32
ACCESS read-write
STATUS mandatory
DESCRIPTION "This is a one minute counter from year 1970.1.1.0:0 to now"
::={foxmail 1}
WeekTime OBJECT-TYPE
SYNTAX TimeTicks
ACCESS read-only
STATUS mandatory
DESCRIPTION "Recording taday's time and the day sorts in the week"
::={foxmail 2}
ExampleTable OBJECT-TYPE
SYNTAX SEQUENCE OF ExampleEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"A list of interface entries. The number of entries is
given by the value of ExampleNumber."
::= { foxmail 3 }
ExampleEntry OBJECT-TYPE
SYNTAX ExampleEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"An entry containing management information applicable to a
particular interface."
INDEX { UserIndex }
::= { ExampleTable 1 }
ExampleEntry ::=
SEQUENCE {
UserIndex InterfaceIndex,
UserStatus DisplayString,
CheckTime TimeTicks,
MonSet Integer32
}
InterfaceIndex ::= TEXTUAL-CONVENTION
DISPLAY-HINT "d"
STATUS current
DESCRIPTION
"A unique value, greater than zero, for each interface or
interface sub-layer in the managed system. It is
recommended that values are assigned contiguously starting
from 1. The value for each interface sub-layer must remain
constant at least from one re-initialization of the entity's
network management system to the next re-initialization."
SYNTAX Integer32 (1..2147483647)
UserIndex OBJECT-TYPE
SYNTAX InterfaceIndex
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"A unique value, greater than zero, for each interface. It
is recommended that values are assigned contiguously
starting from 1. The value for each interface sub-layer
must remain constant at least from one re-initialization of
the entity's network management system to the next re-
initialization."
::= { ExampleEntry 1 }
UserStatus OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"machine status ."
::= { ExampleEntry 2 }
CheckTime OBJECT-TYPE
SYNTAX TimeTicks
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"machine status checking time."
::= { ExampleEntry 3 }
MonSet OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"An example to use set function."
::={ ExampleEntry 4}
END
这个文件在enterprises下定义了一个叫foxmail的节点,oid为1.3.6.1.4.1.310,foxmail下又定义了若干的节点。记的文件的名字一定要和文件第一行DEFINITIONS前的名字对应。
       接下来,把MyMib.txt拷贝到net-snmp的安装目录下,在我机器上是/usr/local/share/snmp/mibs下面。然后要在配置文件snmp.conf里面,把MyMib库加进去。运行snmpconf,就可以对snmp.conf进行设置,具体代码为+MyMib。设置完成后会生成snmp.conf,把这个文件拷贝到/usr/local/share/snmp目录下,接下来,运行mib2c SecondCounter(SecondCounter是MyMib.txt里面的一个结点名字,要添加哪个结点,就在这里写哪个结点名字)。运行完以后,会生成两个文件,SecondCounter.c和SecondCounter.h,这个C文件里就定义了接点的OID,以及各个结点的响应函数,可以根据自己的需求在各个响应函数里面添加对应事件的响应(增加、删除、查询节点的值等)。把这两个文件拷贝到net-snmp的安装包文件下,/opt/net-snmp-5.4.1/agent/mibgroup目录下,然后在运行/opt/net-snmp-5.4.1下的configure命令并且添加参数—with-mib-modules=SecondCounter,进行MIB库文件的配置。配置完毕,在/opt/net-snmp-5.4.1下重新make就完成了对新MIB的添加。
       Make成功以后,运行/opt/net-snmp-5.4.1/agent目录下的snmpd,然后测试一下添加是否成功。用smmptranslate命令查看我们添加的SecondCounter节点的OID号。
命令为Snmptranslate –IR –On SecondCounter,按下回车后,打印出.1.3.6.1.4.1.310.1,这就是我们定义的SecondCounter的OID号,说明我们的私有MIB在MIB库里添加成功。同样也可以查到其他节点存在,那么,就完成了私有MIB的添加。至于节点的值的响应,要根据具体的需求,写对应的函数。如果是要查询交换机里的信息,就要通过响应函数来调用client_switchcall函数,发送对应的消息,来获取需要的值。