【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 ::= 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/
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。