安装net-snmp见:【snmp】centos6.5安装和配置snmp5.7.1
net-snmp添加自定义MIB(标量):【snmp】net-snmp添加自定义MIB(标量)
net-snmp添加自定义MIB(表格) 见:【snmp】net-snmp添加自定义MIB(表格)
一、编写MIB文件
--
-- MyTest-MIB.my
-- MIB generated by MG-SOFT Visual MIB Builder Version 6.0 Build 88
-- Wednesday, August 05, 2020 at 16:51:00
--
MyTest-MIB DEFINITIONS ::= BEGIN
IMPORTS
OBJECT-GROUP
FROM SNMPv2-CONF
enterprises, Integer32, Unsigned32, OBJECT-TYPE, MODULE-IDENTITY
FROM SNMPv2-SMI
DisplayString, RowStatus
FROM SNMPv2-TC;
-- 1.3.6.1.4.1.2020
myModule MODULE-IDENTITY
LAST-UPDATED "202008051610Z" -- August 05, 2020 at 16:10 GMT
ORGANIZATION
"Organization."
CONTACT-INFO
"Contact-info."
DESCRIPTION
"Description."
::= { enterprises 2020 }
--
-- Node definitions
--
-- 1.3.6.1.4.1.2020.1
myOid OBJECT IDENTIFIER ::= { myModule 1 }
-- 1.3.6.1.4.1.2020.1.1
myScalar OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Description."
::= { myOid 1 }
-- 1.3.6.1.4.1.2020.1.2
myTable OBJECT-TYPE
SYNTAX SEQUENCE OF MyEntry
MAX-ACCESS read-create --修改类型为read-create
STATUS current
DESCRIPTION
"Description."
::= { myOid 2 }
-- 1.3.6.1.4.1.2020.1.2.1
myEntry OBJECT-TYPE
SYNTAX MyEntry
MAX-ACCESS read-create --修改类型为read-create
STATUS current
DESCRIPTION
"Description."
INDEX { myIndex }
::= { myTable 1 }
MyEntry ::=
SEQUENCE {
myIndex
Integer32,
mycol1
OCTET STRING,
mycol2
Integer32,
chrs
RowStatus --修改类型为RowStatus
}
-- 1.3.6.1.4.1.2020.1.2.1.1
myIndex OBJECT-TYPE
SYNTAX Integer32 (1..10000)
MAX-ACCESS read-only --根据实际业务修改类型
STATUS current
DESCRIPTION
"Description."
::= { myEntry 1 }
-- 1.3.6.1.4.1.2020.1.2.1.2
mycol1 OBJECT-TYPE
SYNTAX OCTET STRING
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Description."
::= { myEntry 2 }
-- 1.3.6.1.4.1.2020.1.2.1.3
mycol2 OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Description."
::= { myEntry 3 }
-- 1.3.6.1.4.1.2020.1.2.1.4
myrs OBJECT-TYPE
SYNTAX RowStatus --修改为RowStatus
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Description."
::= { myEntry 4 }
END
--
-- MyTest-MIB.my
--
二、使用mib2c命令生成.c和.h文件
2.1使用mib2c.scalar.conf :生成标量对象框架代码
env MIBS="+/usr/local/snmp/share/snmp/mibs/MyTest-MIB.txt" /usr/local/snmp/bin/mib2c -c mib2c.scalar.conf MyTest-MIB::myOid
以上命令执行完后会生成myOid.h和myOid.c文件
2.2使用mib2c.iterate.conf 或 mib2c.mfd.conf :生成表对象框架代码
env MIBS="+/usr/local/snmp/share/snmp/mibs/MyTest-MIB.txt" /usr/local/snmp/bin/mib2c -c mib2c.iterate.conf MyTest-MIB::myModule
以上命令执行完后会生成myModule.h和myModule.c文件
三、修改后的C文件
修改后的myOid.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 "myOid.h"
/** Initializes the myOid module */
void
init_myOid(void)
{
const oid myScalar_oid[] = { 1, 3, 6, 1, 4, 1, 2020, 1, 1 };
DEBUGMSGTL(("myOid", "Initializing\n"));
netsnmp_register_scalar(netsnmp_create_handler_registration
("myScalar", handle_myScalar, myScalar_oid,
OID_LENGTH(myScalar_oid),
HANDLER_CAN_RWRITE));
}
/**定义一个变量*/
static char buff[256]="";
int
handle_myScalar(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_OCTET_STR,
buff, //定义的变量名称buff
strlen(buff) //buff的长度
);
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_OCTET_STR);
if (ret != SNMP_ERR_NOERROR) {
netsnmp_set_request_error(reqinfo, requests, ret);
}
break;
case MODE_SET_RESERVE2:
/*
* XXX malloc "undo" storage buffer
*/
if ( 0/* XXX if malloc, or whatever, failed: */ ) {
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_RESOURCEUNAVAILABLE);
}
break;
case MODE_SET_FREE:
/*
* XXX: free resources allocated in RESERVE1 and/or
* RESERVE2. Something failed somewhere, and the states
* below won't be called.
*/
break;
case MODE_SET_ACTION:
/*
* XXX: perform the value change here
*/
if ( 0/* XXX: error? */ ) {
netsnmp_set_request_error(reqinfo, requests, 0/* some error */
);
}
break;
case MODE_SET_COMMIT:
/*
* XXX: delete temporary storage
*/
memcpy(buff,requests->requestvb->buf,requests->requestvb->val_len); // 赋值
buff[requests->requestvb->val_len] ='\0'; //字符串结束符
if ( 0/* XXX: error? */ ) {
/*
* try _really_really_ hard to never get to this point
*/
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_COMMITFAILED);
}
break;
case MODE_SET_UNDO:
/*
* XXX: UNDO and return to previous value for the object
*/
if ( 0/* XXX: error? */ ) {
/*
* try _really_really_ hard to never get to this point
*/
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_UNDOFAILED);
}
break;
default:
/*
* we should never get here, so this is a really bad error
*/
snmp_log(LOG_ERR, "unknown mode (%d) in handle_myScalar\n",
reqinfo->mode);
return SNMP_ERR_GENERR;
}
return SNMP_ERR_NOERROR;
}
修改后的myModule.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 "myModule.h"
/** Initializes the myModule module */
void
init_myModule(void)
{
/*
* here we initialize all the tables we're planning on supporting
*/
initialize_table_myTable();
}
//注释掉这一行
//# Determine the first/last column names
/** Initialize the myTable table by defining its contents and how it's structured */
void
initialize_table_myTable(void)
{
const oid myTable_oid[] = { 1, 3, 6, 1, 4, 1, 2020, 1, 2 };
const size_t myTable_oid_len = OID_LENGTH(myTable_oid);
netsnmp_handler_registration *reg;
netsnmp_iterator_info *iinfo;
netsnmp_table_registration_info *table_info;
DEBUGMSGTL(("myModule:init", "initializing table myTable\n"));
reg = netsnmp_create_handler_registration("myTable", myTable_handler,
myTable_oid, myTable_oid_len,
HANDLER_CAN_RWRITE);
table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER, /* index: myIndex */
0);
table_info->min_column = COLUMN_MYINDEX;
table_info->max_column = COLUMN_MYRS;
iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);
iinfo->get_first_data_point = myTable_get_first_data_point;
iinfo->get_next_data_point = myTable_get_next_data_point;
iinfo->table_reginfo = table_info;
netsnmp_register_table_iterator(reg, iinfo);
netsnmp_inject_handler_before(reg,
netsnmp_get_cache_handler
(MYTABLE_TIMEOUT, myTable_load,
myTable_free, myTable_oid,
myTable_oid_len), TABLE_ITERATOR_NAME);
/*
* Initialise the contents of the table here
*/
}
#define NNN 1024 //定义这个宏,下面这个结构体用到
/*
* Typical data structure for a row entry
*/
struct myTable_entry {
/*
* Index values
*/
long myIndex;
/*
* Column values
*/
//long myIndex; // 上面已经定义了
char mycol1[NNN];
size_t mycol1_len;
char old_mycol1[NNN];
size_t old_mycol1_len;
long mycol2;
long old_mycol2;
long myrs;
/*
* Illustrate using a simple linked list
*/
int valid;
struct myTable_entry *next;
};
struct myTable_entry *myTable_head;
/*
* create a new row in the (unsorted) table
*/
struct myTable_entry *
//补全这个函数的参数,其实就是表格中那三列的内容
//这个函数就是添加一行数据的函数,RowStatus列不传也可以,程序内部会自动处理
myTable_createEntry(long myIndex,char *mycol1,size_t mycol1_len,long mycol2)
{
struct myTable_entry *entry;
entry = SNMP_MALLOC_TYPEDEF(struct myTable_entry);
if (!entry)
return NULL;
entry->myIndex = myIndex;
snprintf(entry->mycol1, sizeof(entry->mycol1), "%s", mycol1); //将mycol1数据赋给结构体
entry->mycol1_len = mycol1_len; //将mycol1_len数据赋给结构体
entry->mycol2 = mycol2; //将mycol2数据赋给结构体
entry->next = myTable_head;
myTable_head = entry;
return entry;
}
/*
* remove a row from the table
*/
void
myTable_removeEntry(struct myTable_entry *entry)
{
struct myTable_entry *ptr, *prev;
if (!entry)
return; /* Nothing to remove */
for (ptr = myTable_head, prev = NULL;
ptr != NULL; prev = ptr, ptr = ptr->next) {
if (ptr == entry)
break;
}
if (!ptr)
return; /* Can't find it */
if (prev == NULL)
myTable_head = ptr->next;
else
prev->next = ptr->next;
SNMP_FREE(entry); /* XXX - release any other internal resources */
}
#define STRMAX 1024 //定义宏
/*
* Example cache handling - set up linked list from a suitable file
*/
int
myTable_load(netsnmp_cache * cache, void *vmagic)
{
FILE *fp;
struct myTable_entry *this;
char buf[STRMAX];
/*
* The basic load routine template assumes that the data to
* be reported is held in a file - with one row of the file
* for each row of the table.
* If your data is available via a different API, you
* should amend this initial block (and the control of the
* 'while' loop) accordingly.
* 'XXX' marks where the template is incomplete and
* code will definitely need to be added.
*/
fp = fopen("/data/for/myTable", "r");
if (!fp) {
return -1;
}
while (fgets(buf, STRMAX, fp)) {
this = SNMP_MALLOC_TYPEDEF(struct myTable_entry);
/*
* XXX - Unpick 'buf' to extract the individual field values
* and then populate the 'this' data structure with them
*/
this->next = myTable_head;
myTable_head = this; /* Iterate helper is fine with unordered lists! */
}
fclose(fp);
return 0; /* OK */
}
void
myTable_free(netsnmp_cache * cache, void *vmagic)
{
struct myTable_entry *this, *that;
for (this = myTable_head; this; this = that) {
that = this->next;
SNMP_FREE(this); /* XXX - release any other internal resources */
}
myTable_head = NULL;
}
/*
* Example iterator hook routines - using 'get_next' to do most of the work
*/
netsnmp_variable_list *
myTable_get_first_data_point(void **my_loop_context,
void **my_data_context,
netsnmp_variable_list * put_index_data,
netsnmp_iterator_info *mydata)
{
*my_loop_context = myTable_head;
return myTable_get_next_data_point(my_loop_context, my_data_context,
put_index_data, mydata);
}
netsnmp_variable_list *
myTable_get_next_data_point(void **my_loop_context,
void **my_data_context,
netsnmp_variable_list * put_index_data,
netsnmp_iterator_info *mydata)
{
struct myTable_entry *entry =
(struct myTable_entry *) *my_loop_context;
netsnmp_variable_list *idx = put_index_data;
if (entry) {
snmp_set_var_typed_integer(idx, ASN_INTEGER, entry->myIndex);
idx = idx->next_variable;
*my_data_context = (void *) entry;
*my_loop_context = (void *) entry->next;
return put_index_data;
} else {
return NULL;
}
}
/** handles requests for the myTable table */
int
myTable_handler(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
netsnmp_request_info *request;
netsnmp_table_request_info *table_info;
struct myTable_entry *table_entry;
struct myTable_entry *table_row; //这个变量未定义
int ret; //变量未定义
DEBUGMSGTL(("myModule:handler", "Processing request (%d)\n",
reqinfo->mode));
switch (reqinfo->mode) {
/*
* Read-support (also covers GetNext requests)
*/
case MODE_GET:
for (request = requests; request; request = request->next) {
table_entry = (struct myTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_MYINDEX:
if (!table_entry) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
table_entry->myIndex);
break;
case COLUMN_MYCOL1:
if (!table_entry) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
table_entry->mycol1,
table_entry->mycol1_len);
break;
case COLUMN_MYCOL2:
if (!table_entry) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
table_entry->mycol2);
break;
case COLUMN_MYRS:
if (!table_entry) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
table_entry->myrs);
break;
default:
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHOBJECT);
break;
}
}
break;
/*
* Write-support
*/
case MODE_SET_RESERVE1:
for (request = requests; request; request = request->next) {
table_entry = (struct myTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_MYCOL1:
/*
* or possibly 'netsnmp_check_vb_type_and_size'
*/
ret =
netsnmp_check_vb_type_and_max_size(request->requestvb,
ASN_OCTET_STR,
sizeof(table_entry->
mycol1));
if (ret != SNMP_ERR_NOERROR) {
netsnmp_set_request_error(reqinfo, request, ret);
return SNMP_ERR_NOERROR;
}
break;
case COLUMN_MYCOL2:
/*
* or possibly 'netsnmp_check_vb_int_range'
*/
ret = netsnmp_check_vb_int(request->requestvb);
if (ret != SNMP_ERR_NOERROR) {
netsnmp_set_request_error(reqinfo, request, ret);
return SNMP_ERR_NOERROR;
}
break;
case COLUMN_MYRS:
ret = netsnmp_check_vb_rowstatus(request->requestvb,
(table_entry ? RS_ACTIVE :
RS_NONEXISTENT));
if (ret != SNMP_ERR_NOERROR) {
netsnmp_set_request_error(reqinfo, request, ret);
return SNMP_ERR_NOERROR;
}
break;
default:
netsnmp_set_request_error(reqinfo, request,
SNMP_ERR_NOTWRITABLE);
return SNMP_ERR_NOERROR;
}
}
break;
case MODE_SET_RESERVE2:
for (request = requests; request; request = request->next) {
table_entry = (struct myTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_MYRS:
switch (*request->requestvb->val.integer) {
case RS_CREATEANDGO:
case RS_CREATEANDWAIT:
table_row =
myTable_createEntry(*table_info->indexes->val.integer,"",0,0);//补全,这里是创建一个新的行
if (table_row) {
netsnmp_insert_iterator_context(request,
table_row);
} else {
netsnmp_set_request_error(reqinfo, request,
SNMP_ERR_RESOURCEUNAVAILABLE);
return SNMP_ERR_NOERROR;
}
}
}
}
break;
case MODE_SET_FREE:
for (request = requests; request; request = request->next) {
table_entry = (struct myTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_MYRS:
switch (*request->requestvb->val.integer) {
case RS_CREATEANDGO:
case RS_CREATEANDWAIT:
if (table_entry && !table_entry->valid) {
myTable_removeEntry(table_row); //多传了table_data参数,删除
}
}
}
}
break;
case MODE_SET_ACTION:
for (request = requests; request; request = request->next) {
table_entry = (struct myTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_MYCOL1:
memcpy(table_entry->old_mycol1,
table_entry->mycol1, sizeof(table_entry->mycol1));
table_entry->old_mycol1_len = table_entry->mycol1_len;
memset(table_entry->mycol1, 0,
sizeof(table_entry->mycol1));
memcpy(table_entry->mycol1,
request->requestvb->val.string,
request->requestvb->val_len);
table_entry->mycol1_len = request->requestvb->val_len;
break;
case COLUMN_MYCOL2:
table_entry->old_mycol2 = table_entry->mycol2;
table_entry->mycol2 = *request->requestvb->val.integer;
break;
}
}
/*
* Check the internal consistency of an active row
*/
for (request = requests; request; request = request->next) {
table_entry = (struct myTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_MYRS:
switch (*request->requestvb->val.integer) {
case RS_ACTIVE:
case RS_CREATEANDGO:
if ( 0/* 出错条件 */ ) {
netsnmp_set_request_error(reqinfo, request,
SNMP_ERR_INCONSISTENTVALUE);
return SNMP_ERR_NOERROR;
}
}
}
}
break;
case MODE_SET_UNDO:
for (request = requests; request; request = request->next) {
table_entry = (struct myTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_MYCOL1:
memcpy(table_entry->mycol1,
table_entry->old_mycol1,
sizeof(table_entry->mycol1));
memset(table_entry->old_mycol1, 0,
sizeof(table_entry->mycol1));
table_entry->mycol1_len = table_entry->old_mycol1_len;
break;
case COLUMN_MYCOL2:
table_entry->mycol2 = table_entry->old_mycol2;
table_entry->old_mycol2 = 0;
break;
case COLUMN_MYRS:
switch (*request->requestvb->val.integer) {
case RS_CREATEANDGO:
case RS_CREATEANDWAIT:
if (table_entry && !table_entry->valid) {
myTable_removeEntry(table_row);//多传了table_data参数,删除
}
}
break;
}
}
break;
case MODE_SET_COMMIT:
for (request = requests; request; request = request->next) {
table_entry = (struct myTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_MYRS:
switch (*request->requestvb->val.integer) {
case RS_CREATEANDGO:
table_entry->valid = 1;
/*
* Fall-through
*/
case RS_ACTIVE:
table_entry->myrs = RS_ACTIVE;
break;
case RS_CREATEANDWAIT:
table_entry->valid = 1;
/*
* Fall-through
*/
case RS_NOTINSERVICE:
table_entry->myrs = RS_NOTINSERVICE;
break;
case RS_DESTROY:
myTable_removeEntry(table_entry);//修改table_row为table_entry,否则删除行不成功,多传了table_data参数,删除
}
}
}
break;
}
return SNMP_ERR_NOERROR;
}
四、载入自定义MIB库
1、在服务器/root/net-snmp-5.7.1/agent/mibgroup/目录下新建一个目录mytest-mib。将生成的myOid.h、myOid.h和修改后的myModule.c 、myModule.c文件放到mytest-mib目录下。
在/root/net-snmp-5.7.1/agent/mibgroup目录下新建文件mytest.h
mytest.h文件内容为:
config_require(mytest-mib/myOid); config_require(mytest-mib/myModule);
2、如果snmp服务在运行,停止snmp服务
3、在/root/net-snmp-5.7.1目录下依次执行下面3个命令编译安装
./configure --prefix=/usr/local/snmp --with-mib-modules="mytest"
make
make install
五、测试
1、执行/usr/local/snmp/sbin/snmpd -c /usr/local/snmp/etc/snmpd.conf 命令启动snmp服务
测试标量
1、设置myNode的值为"harara"
/usr/local/snmp/bin/snmpset -v 2c -c public localhost 1.3.6.1.4.1.2020.1.1.0 s harara
2、查看myNode的值
/usr/local/snmp/bin/snmpget -v 2c -c public localhost 1.3.6.1.4.1.2020.1.1.0
测试表格
1、执行/usr/local/snmp/bin/snmpwalk -v 2c -c public localhost 1.3.6.1.4.1.2020.1.2查看表格内容,可以看到表里什么都没有
2、添加第一行数据:/usr/local/snmp/bin/snmpset -v 2c -c public localhost 1.3.6.1.4.1.2020.1.2.1.4.1 i 4
这个命令表示对表的第一行的第三列设置值为4,因为第三列为RowStatus类型,所以系统会创建这一行
(表中原本是没有第一行的,只要对第一行的RowStatus列写入4就可以创建这一行)
3、设置字段值, 例:设置第一行数据中的myCol1字段:/usr/local/snmp/bin/snmpset -v 2c -c public localhost 1.3.6.1.4.1.2020.1.2.1.2.1 s harara
4、删除第1行,对第1行的第4列写入6即可:/usr/local/snmp/bin/snmpset -v 2c -c public localhost 1.3.6.1.4.1.2020.1.2.1.4.1 i 6
参考地址
作者:小念
出处:https://www.cnblogs.com/kiko2014551511/
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。