本文主要是介绍【snmp】net-snmp添加自定义MIB(标量和表格),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
安装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 ::= BEGINIMPORTSOBJECT-GROUP FROM SNMPv2-CONF enterprises, Integer32, Unsigned32, OBJECT-TYPE, MODULE-IDENTITY FROM SNMPv2-SMIDisplayString, RowStatus FROM SNMPv2-TC; -- 1.3.6.1.4.1.2020myModule MODULE-IDENTITY LAST-UPDATED "202008051610Z" -- August 05, 2020 at 16:10 GMTORGANIZATION "Organization."CONTACT-INFO "Contact-info."DESCRIPTION "Description."::= { enterprises 2020 }-- -- Node definitions ---- 1.3.6.1.4.1.2020.1myOid OBJECT IDENTIFIER ::= { myModule 1 }-- 1.3.6.1.4.1.2020.1.1myScalar OBJECT-TYPESYNTAX DisplayStringMAX-ACCESS read-writeSTATUS currentDESCRIPTION"Description."::= { myOid 1 }-- 1.3.6.1.4.1.2020.1.2myTable OBJECT-TYPESYNTAX SEQUENCE OF MyEntryMAX-ACCESS read-create --修改类型为read-createSTATUS currentDESCRIPTION"Description."::= { myOid 2 }-- 1.3.6.1.4.1.2020.1.2.1myEntry OBJECT-TYPESYNTAX MyEntryMAX-ACCESS read-create --修改类型为read-createSTATUS currentDESCRIPTION"Description."INDEX { myIndex }::= { myTable 1 }MyEntry ::=SEQUENCE { myIndexInteger32,mycol1OCTET STRING,mycol2Integer32,chrsRowStatus --修改类型为RowStatus}-- 1.3.6.1.4.1.2020.1.2.1.1myIndex OBJECT-TYPESYNTAX Integer32 (1..10000)MAX-ACCESS read-only --根据实际业务修改类型STATUS currentDESCRIPTION"Description."::= { myEntry 1 }-- 1.3.6.1.4.1.2020.1.2.1.2mycol1 OBJECT-TYPESYNTAX OCTET STRINGMAX-ACCESS read-writeSTATUS currentDESCRIPTION"Description."::= { myEntry 2 }-- 1.3.6.1.4.1.2020.1.2.1.3mycol2 OBJECT-TYPESYNTAX Integer32MAX-ACCESS read-writeSTATUS currentDESCRIPTION"Description."::= { myEntry 3 }-- 1.3.6.1.4.1.2020.1.2.1.4myrs OBJECT-TYPESYNTAX RowStatus --修改为RowStatusMAX-ACCESS read-createSTATUS currentDESCRIPTION"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, //定义的变量名称buffstrlen(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;elseprev->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
参考地址
利用mib2c生成框架代码
作者:小念
出处:https://www.cnblogs.com/kiko2014551511/
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
这篇关于【snmp】net-snmp添加自定义MIB(标量和表格)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!