参考:http://blog.csdn.net/shanzhizi/article/details/11769491
用net-snmp扩展MIB库,实现方法可归结为四种:
1)一是静态库方式,通过修改配置头文件,在相应地方包含新引入的mib模块的.c和.h文件,然后重新编译库文件和扩展代码;这种方式不够灵活,每次修改扩展的MIB后,都需要重新编译snmpd和扩展的代码,再重新安装snmpd到系统中。
2)二是编译动态共享库,只需把新引入的MIB模块的.c和.h文件编译成动态库,通过设置能够让代理程序载入。
对于第二种方式,一需要编译成.so动态共享库,二需要原代理程序是否包含dlmod或load命令,三还要看系统是否支持。一般情况下仅支持Unix平台。
3)三是扩展一个子代理,让SNMPD以主代理的模式运行,对于SNMPD我们只要让它启动就可以,不需要任何的更改和配置,把子代理编译生成的程序运行起来就可以扩展自定义的MIB库。
4)用shell脚本来扩展
本文我们以第三种方法在linux上开发和测试
编写mib文件
mib文件的作用:
1、开发方便生成扩展程序的.c和.h
2、用户访问的时候,可以不用输oid,直接输节点名就可以访问。
注:编写mib文件可以用window下的一个软件方便编写,名字叫MG-SOFT MIB Browser
mib文件放在的目录在/usr/local/net-snmp/share/snmp/mibs下
自定义MIB库,如下:
-
-- Test-MIB.my
-
Test-MIB DEFINITIONS ::= BEGIN
-
-
IMPORTS
-
OBJECT-GROUP, MODULE-COMPLIANCE, NOTIFICATION-GROUP
-
FROM SNMPv2-CONF
-
enterprises, Integer32, Unsigned32, OBJECT-TYPE, MODULE-IDENTITY,
-
NOTIFICATION-TYPE
-
FROM SNMPv2-SMI
-
DisplayString
-
FROM SNMPv2-TC;
-
-
-- October 09, 2002 at 14:50 GMT
-
-- 1.3.6.1.4.1.16535
-
Test MODULE-IDENTITY
-
LAST-UPDATED "200210091450Z" -- October 09, 2002 at 14:50 GMT
-
ORGANIZATION
-
""
-
CONTACT-INFO
-
""
-
DESCRIPTION
-
"Video's Server MIB."
-
::= { enterprises 16535 }
-
-
-- Node definitions
-
-- This part will include all details about the Test.
-
-- 1.3.6.1.4.1.16535.1
-
Time OBJECT IDENTIFIER ::= { Test 1 }
-
-
-
-- 1.3.6.1.4.1.16535.1.1
-
GetTime OBJECT-TYPE
-
SYNTAX DisplayString (SIZE (0..100))
-
MAX-ACCESS read-only
-
STATUS current
-
DESCRIPTION
-
"Example : 2013/4/11"
-
::= { Time 1 }
-
END
-
-
-- Test-MIB.my
-
-
每个oid必须是唯一的,1.3.6.1.4.1.16535.1.1,写完后我们测一个MIB库有没有问题,在linux机器上用snmptranslate -Tp -IR Test-MIB::Test显示结果如下:
-
+--Test(16535)
-
|
-
+--Time(1)
-
|
-
+-- -R-- String GetTime(1)
-
Textual Convention: DisplayString
-
Size: 0..100
生成源码
生成源码需要用到mib2c这个工具,需要先配置一下snmp.conf文件,在
/usr/local/net-snmp/share/snmp/
snmp.conf
-
mibdirs /usr/local/net-snmp/share/snmp/mibs
-
mibs +ALL
记得改环境配置,否则在其他目录生成的话,不识别mib2c命令和用到的conf文件和文件。
我在~/.bashrc里的配置
mib2c可以根据mib库生成对应的源代码,有多种模板,这里我用固定的套路去生成
使用命令mib2c Test,先选2,后选1。1是生成string型,2是生成int型。
这是会发现在目录下多了一个.c和一个.h文件。
.h文件如下
-
/*
-
* Note: this file originally auto-generated by mib2c using
-
* $
-
*/
-
#ifndef TEST_H
-
#define TEST_H
-
-
/*
-
* function declarations
-
*/
-
void init_Test(void);
-
Netsnmp_Node_Handler handle_GetTime;
-
-
#endif
.c文件
-
/*
-
* Note: this file originally auto-generated by mib2c using
-
* $
-
*/
-
-
#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 GetTime_oid[] = { 1, 3, 6, 1, 4, 1, 16535, 1, 1 };
-
-
DEBUGMSGTL(("Test", "Initializing\n"));
-
-
netsnmp_register_scalar(netsnmp_create_handler_registration
-
("GetTime", handle_GetTime, GetTime_oid,
-
OID_LENGTH(GetTime_oid), HANDLER_CAN_RONLY));
-
}
-
-
int
-
handle_GetTime(netsnmp_mib_handler *handler,
-
netsnmp_handler_registration *reginfo,
-
netsnmp_agent_request_info *reqinfo,
-
netsnmp_request_info *requests)
-
{
-
/*
-
* 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_OCTET_STR,
-
/*
-
* XXX: a pointer to the scalar's data
-
*/ ,
-
/*
-
* XXX: the length of the data in bytes
-
*/ );
-
break;
-
-
-
default:
-
/*
-
* we should never get here, so this is a really bad error
-
*/
-
snmp_log(LOG_ERR, "unknown mode (%d) in handle_GetTime\n",
-
reqinfo->mode);
-
return SNMP_ERR_GENERR;
-
}
-
-
return SNMP_ERR_NOERROR;
-
}
修改.c文件如下
-
/*
-
* Note: this file originally auto-generated by mib2c using
-
* $
-
*/
-
-
#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"
-
#include <time.h>
-
-
/** Initializes the Test module */
-
void
-
init_Test(void)
-
{
-
const oid GetTime_oid[] = { 1, 3, 6, 1, 4, 1, 16535, 1, 1 };
-
-
DEBUGMSGTL(("Test", "Initializing\n"));
-
-
netsnmp_register_scalar(netsnmp_create_handler_registration
-
("GetTime", handle_GetTime, GetTime_oid,
-
OID_LENGTH(GetTime_oid), HANDLER_CAN_RONLY));
-
}
-
-
int
-
handle_GetTime(netsnmp_mib_handler *handler,
-
netsnmp_handler_registration *reginfo,
-
netsnmp_agent_request_info *reqinfo,
-
netsnmp_request_info *requests)
-
{
-
/*
-
* 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.
-
*/
-
-
time_t t;
-
switch (reqinfo->mode) {
-
case MODE_GET:
-
time(&t);
-
char szTime[100];
-
snprintf(szTime,100,"%s",ctime(&t));
-
snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
-
/*
-
* XXX: a pointer to the scalar's data
-
*/ szTime,
-
/*
-
* XXX: the length of the data in bytes
-
*/ strlen(szTime));
-
break;
-
-
-
default:
-
/*
-
* we should never get here, so this is a really bad error
-
*/
-
snmp_log(LOG_ERR, "unknown mode (%d) in handle_GetTime\n",
-
reqinfo->mode);
-
return SNMP_ERR_GENERR;
-
}
-
-
return SNMP_ERR_NOERROR;
-
}
编译该.c文件,执行命令:
net-snmp-config --compile-subagent Test Test.c,生成一个Test可执行文件。
其实,net-snmp-config程序生成了一个临时的C文件,netsnmptmp.12373.c 并与Test.c一起编译,生成了Test程序后又删除了该临时文件。在这里就不研究了。
我们先执行主代理(service snmpd start),再执行子代理./Test,再ps -ef | grep Test,看一下,可以看到Test程序自动在后台启动了。
执行命令:
snmpget -v2c -c public localhost 1.3.6.1.4.1.16535.1.1.0
snmpget -v2c -c public localhost Test-MIB:GetTime.0
可以获得该节点的值。
将.c文件加入项目中
-
/*
-
* Note: this file originally auto-generated by mib2c using
-
* $
-
*/
-
-
#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"
-
#include <time.h>
-
-
/** Initializes the Test module */
-
void
-
init_Test(void)
-
{
-
const oid GetTime_oid[] = { 1, 3, 6, 1, 4, 1, 16535, 1, 1 };
-
-
DEBUGMSGTL(("Test", "Initializing\n"));
-
-
netsnmp_register_scalar(netsnmp_create_handler_registration
-
("GetTime", handle_GetTime, GetTime_oid,
-
OID_LENGTH(GetTime_oid), HANDLER_CAN_RONLY));
-
}
-
-
int
-
handle_GetTime(netsnmp_mib_handler *handler,
-
netsnmp_handler_registration *reginfo,
-
netsnmp_agent_request_info *reqinfo,
-
netsnmp_request_info *requests)
-
{
-
/*
-
* 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.
-
*/
-
-
time_t t;
-
switch (reqinfo->mode) {
-
case MODE_GET:
-
time(&t);
-
char szTime[100];
-
snprintf(szTime,100,"%s",ctime(&t));
-
snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
-
/*
-
* XXX: a pointer to the scalar's data
-
*/ szTime,
-
/*
-
* XXX: the length of the data in bytes
-
*/ strlen(szTime));
-
break;
-
-
-
default:
-
/*
-
* we should never get here, so this is a really bad error
-
*/
-
snmp_log(LOG_ERR, "unknown mode (%d) in handle_GetTime\n",
-
reqinfo->mode);
-
return SNMP_ERR_GENERR;
-
}
-
-
return SNMP_ERR_NOERROR;
-
}
-
-
static int keep_running;
-
RETSIGTYPE stop_server(int __attribute__((unused)) a) {
-
keep_running = 0;
-
}
-
-
int main()
-
{
-
const char *app_name = "Test";
-
/* we are a subagent */
-
netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1);
-
-
/* initialize the agent library */
-
init_agent(app_name);
-
-
/* initialize your mib code here */
-
init_Test(); //如果还需添加扩展,只需将生成.c中的init_*()函数添加到此就可以了。
-
-
/* Test will be used to read Test.conf files. */
-
init_snmp(app_name);
-
keep_running = 1;
-
while(keep_running)
-
{
-
agent_check_and_process(1);/* block every 1 second */
-
}
-
/* at shutdown time */
-
snmp_shutdown(app_name);
-
-
/* deinitialize your mib code here */
-
-
/* shutdown the agent library */
-
shutdown_agent();
-
return 0;
-
}
编译改函数使用gcc,编译,需要用到/usr/local/net-snmp/include里的头文件,和/usr/local/net-snmp/lib的库文件,libnetsnmp和libnetsnmpagent的动态的或者静态的库都行。使用动态库的话,记得在函数执行前修改ld.so.conf中添加动态库的路径,修改完以后记得ldconfig,更新一下。
执行生成的可执行文件,打印出“
NET-SNMP version 5.7.2 AgentX subagent connected ”即为该程序执行成功。
可以调用snmpget去测试。
其他的扩展方式
1、动态库扩展
编译命令: net-snmp-config --compile-subagent Test.so Test.c -fPIC -shared
在snmpd.conf文件中添加 “dlmod Test /usr/local/net-snmp/share/snmp/mibs/Test.so”即可。
2、shell扩展:
在snmpd.conf文件中添加 “extend .1.3.6.1.4.1.16535.1.1 /bin/sh gettime.sh”
阅读(3121) | 评论(0) | 转发(0) |