我所知道的添加自定義MIB的方法有三種
1.靜態加載,將生成的.c和.h文件加入到相應的位置,重新編譯snmp庫,優點是不需要修改配置文件,缺點是每次添加都得重新編譯;
2.動態加載,將生成的.c和.h文件再編譯成.so庫,修改snmpd.conf配置文件。優點是每次添加不需要重新編譯,缺點是必須支持dlmod命令;
3.子代理擴展,將生成的.c和.h文件編譯成可執行程序,運行該程序和snmpd即可,優點是操作簡單,缺點是需要運行兩個程序才行。
三種方法的前幾步是一樣的,都是編寫MIB,生成.c和.h文件,補全.c文件。
1.編寫MIB
MIB的語法見
http://blog.csdn.net/shanzhizi/article/details/15340305,寫得很清楚,很詳細。
下面給出我自己的MIB文件。
-- Test-SLK-MIB.txt
Test-SLK-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;
Test MODULE-IDENTITY
LAST-UPDATED "201601221450Z" --必須以Z結尾
ORGANIZATION
""
CONTACT-INFO
""
DESCRIPTION
"Video's Server MIB."
::= { enterprises 745352 }
Time OBJECT IDENTIFIER ::= { Test 1 }
GetTime OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Example : 2016/1/22"
::= { Time 1 }
END
-- Test-SLK-MIB.txt
這個MIB文件很簡單,只有一個OID 1.3.6.1.4.1.745352.1.1,把這個MIB放入MIBS文件夾,我的位於/usr/local/snmp/share/snmp/mibs。
2.生成.c和.h文件
運行命令mib2c Test-SLK-MIB::Test 出現的選項依次選2和1.
[root@localhost mibs]# env MIBS="+/etc/snmp/mibs/Test-MIB.my" 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.16535
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):
1) ucd-snmp style code
2) Net-SNMP style code
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
* $
*/
#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, 745352, 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;
}
3.補全Test.c
在代碼中XXX處添加相應的值,代碼中都有說明,XXX: a pointer to the scalar's data,這個要我們填一個指針,XXX: the length of the data in bytes 這個要我們填數據的大小,當然要先定義,然后去獲取啊。
補全后
/*
* 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, 745352, 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;
}
接下來根據方法不同,步驟也不同。
一、靜態鏈接
把Test.c和Test.h復制到/net-snmp-5.7.3/agent/mibgroups,這里是說net-snmp源碼里。
編譯./configure --prefix=/usr/local/snmp --with-mib-modules=Test,make && make install。
靜態加載成功
二、動態加載
編寫makefile文件
CC=gcc
FLAGS=-I. `net-snmp-config --cflags` -g
DLFLAGS=-shared -fPIC -g
Test.so: Test.c
$(CC) $(CFLAGS) $(DLFLAGS) -c -o Test.o Test.c
$(CC) $(CFLAGS) $(DLFLAGS) -o Test.so Test.o
.PHONY : clean
clean :
rm -f *.so *.o
編譯生成.so庫。
修改snmpd.conf配置文件,在文件末尾加入dlmod Test ${Test.so所在絕對路徑}/Test.so
啟動snmpd,
/usr/local/snmpd -f -L -DTest,dlmod -c /usr/local/snmp/etc/snmpd.conf
動態加載完成
三、子代理擴展
生成Test程序:
net-snmp-config --compile-subagent Test Test.c
啟動snmpd,Test
/usr/local/snmpd -c /usr/local/snmp/etc/snmpd.conf
./Test
完成