文章目录
前言
本篇主要介绍如何使用开源代码net-snmp来构建自己的代理程序,实现自己的专属业务。net-snmp支持静态编译、动态库加载、子代理加载三种方式扩展MIB,构建代理。
一、下载编译net-snmp
1、从net-snmp官方网站http://www.net-snmp.org/download.html下载net-snmp-5.9.3源码。
2、配置编译环境
./configure --prefix=/usr/local/snmpd --enable-ipv6 --with-openssl
–prefix=/usr/local/snmpd 编译生成目标文件放置目录
–enable-ipv6 支持IPV6
–with-openssl 编译带openssl
中间过程全部选择默认,完成后显示配置信息如下:
3、编译
make -j4
-j是多线程编译,提高编译速度
4、拷贝生成文件到/usr/local/snmpd目录
make install
二、创建MIB文件
1.创建MIB
我们先创建一个简单的MIB文件myTest.mib,含有一个读写权限的节点testObject ,保存到 /usr/local/snmpd/share/snmp/mibs/ 目录。
--开始
TEST-MIB DEFINITIONS ::= BEGIN
--引入部分
IMPORTS
enterprises
FROM RFC1155-SMI
Integer32,OBJECT-TYPE
FROM SNMPv2-SMI
DisplayString
FROM SNMPv2-TC
TEXTUAL-CONVENTION
FROM SNMPv2-TC; --引用结束,用分号
--定义节点
--enterprises的OID是1.3.6.1.4.1
test OBJECT IDENTIFIER ::= {
enterprises 8888}
testObject OBJECT IDENTIFIER ::= {
test 1}
testObject OBJECT-TYPE --对象名称
SYNTAX Integer32 --类型
MAX-ACCESS read-write --访问方式
STATUS current --状态
DESCRIPTION "test write" --描述
::= {
test 1} --父节点
--结束定义
END
2.使用 snmptranslate查看MIB加载
然后使用 snmptranslate 查看自定义的 TEST-MIB 是否被加载
/usr/local/snmpd/bin/snmptranslate -Tp -IR TEST-MIB::test
+--test(8888)
|
+-- -RW- Integer32 testObject(1)
3.查询OID
我们先来获取一下前面定义的 testObject 节点试试。 因为 enterprises 的OID是 1.3.6.1.4.1 ,而 test 是 enterprises 的叶子节点(8888),而 testObject 又是 test 的叶子节点(1)。所以其OID为 1.3.6.1.4.1.8888.1 。
下面使用snmpget来测试一下 ,找不到OID
./snmpget -v2c -c public localhost 1.3.6.1.4.1.8888.1
SNMPv2-SMI::enterprises.8888.1 = No Such Object available on this agent at this OID
三、使用MIB2C生成.c和.h文件
执行以下命令生成.c和.h文件,其中test表示要生成文件的MIB节点名称。
MIBS="+/usr/local/snmpd/share/snmp/mibs/myTest.mib" /usr/local/snmpd/bin/mib2c test
命令执行后显示如下:
writing to -
mib2c has multiple configuration files depending on the type of
code you need to write. You must pick one depending on your need.
You requested mib2c to be run on the following part of the MIB tree:
OID: test
numeric translation: .1.3.6.1.4.1.8888
number of scalars within: 1
number of tables within: 0
number of notifications within: 0
First, do you want to generate code that is compatible with the
ucd-snmp 4.X line of code, or code for the newer Net-SNMP 5.X code
base (which provides a much greater choice of APIs to pick from). You
can also generate C-header files containing define statements for
column numbers, enums, etc. Or do you simply want to translate the
MIB structures into documentation?
1) ucd-snmp style code
2) Net-SNMP style code
3) Generate header files
4) Generate documentation
Select your choice : 2
**********************************************************************
GENERATING CODE FOR SCALAR OBJECTS:
**********************************************************************
It looks like you have some scalars in the mib you requested, so I
will now generate code for them if you wish. You have two choices
for scalar API styles currently. Pick between them, or choose not
to generate any code for the scalars:
1) If you're writing code for some generic scalars
(by hand use: "mib2c -c mib2c.scalar.conf test")
2) If you want to magically "tie" integer variables to integer
scalars
(by hand use: "mib2c -c mib2c.int_watch.conf test")
3) Don't generate any code for the scalars
Select your choice: 1
using the mib2c.scalar.conf configuration file to generate your code.
writing to test.h
writing to test.c
**********************************************************************
* NOTE WELL: The code generated by mib2c is only a template. *YOU* *
* must fill in the code before it'll work most of the time. In many *
* cases, spots that MUST be edited within the files are marked with *
* /* XXX */ or /* TODO */ comments. *
**********************************************************************
running indent on test.h
running indent on test.c
生成test.c文件如下:
/*
* Note: this file originally auto-generated by mib2c
* using mib2c.scalar.conf
*/
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "test.h"
/** Initializes the test module */
void
init_test(void)
{
const oid testObject_oid[] = {
1,3,6,1,4,1,8888,1 };
DEBUGMSGTL(("test", "Initializing\n"));
netsnmp_register_scalar(
netsnmp_create_handler_registration("testObject", handle_testObject,
testObject_oid, OID_LENGTH(testObject_oid),
HANDLER_CAN_RWRITE
));
}
int
handle_testObject(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
int ret;
/* We are never called for a GETNEXT if it's registered as a
"instance", as it's "magically" handled for us. */
/* a instance handler also only hands us one request at a time, so
we don't need to loop over a list of requests; we'll only get one. */
switch(reqinfo->mode) {
case MODE_GET:
snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
/* XXX: a pointer to the scalar's data */,
/* XXX: the length of the data in bytes */);
break;
/*
* SET REQUEST
*
* multiple states in the transaction. See:
* http://www.net-snmp.org/tutorial-5/toolkit/mib_module/set-actions.jpg
*/
case MODE_SET_RESERVE1:
/* or you could use netsnmp_check_vb_type_and_size instead */
ret = netsnmp_check_vb_type(requests->requestvb, ASN_INTEGER