snmp 表格支持增删改查操作,比标量节点多了增删操作,那么为了实现增删操作,可以向表格增加一个RowStatus行状态类型的列,通过设置状态值对表格进行控制。
RowStatus状态值
状态 | 说明 |
---|---|
active(1) | 表明状态行是可用的 |
notInService(2) | 表明行存在但不可用 |
notReady (3) | 表明行存在,但因为缺少必要的信息而不能用 |
createAndGo (4) | 由管理者设置,表明希望创建一个行并设置该行的状态列对象为active |
createAndWait(5) | 由管理者设置,表明希望创建一个行,但不可用,从上面的代码看到,是被设置为了notInService |
destroy(6) | 删除行 |
一、编写mib文件
使用MIB Builder生成MIB文件见:【snmp】使用MIB Builder生成MIB文件
注意
1、要有一个index索引节点,但是这个索引的名称不能为"index",为"index"会报错,我这里索引名称是为"userIdx"
2、一般会设置最后一列为RowStatus列,实际使用时除了RowStatus对应的节点需要设置read-create,其他节点可以随便设置,但是在MIB Builder工具中设置了一列为read-create,其他列(除索引列)也要设置为read-create,否则会报错,因此请将表的各个节点均设置为read-create类型,后面我们再修改生成的MIB文件
生成的UserTable-MIB.my文件内容如下:
--
-- UserTable-MIB.my
-- MIB generated by MG-SOFT Visual MIB Builder Version 6.0 Build 88
-- Thursday, August 06, 2020 at 14:12:31
--
UserTable-MIB DEFINITIONS ::= BEGIN
IMPORTS
OBJECT-GROUP
FROM SNMPv2-CONF
enterprises, Integer32, OBJECT-TYPE, MODULE-IDENTITY
FROM SNMPv2-SMI;
-- 1.3.6.1.4.1.85
myModule MODULE-IDENTITY
LAST-UPDATED "202008071136Z" -- August 07, 2020 at 11:36 GMT
ORGANIZATION
"Organization."
CONTACT-INFO
"Contact-info."
DESCRIPTION
"Description."
::= { enterprises 85 }
--
-- Node definitions
--
-- 1.3.6.1.4.1.85.1
user OBJECT IDENTIFIER ::= { myModule 1 }
-- 1.3.6.1.4.1.85.1.1
userTable OBJECT-TYPE
SYNTAX SEQUENCE OF UserEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Description."
::= { user 1 }
-- 1.3.6.1.4.1.85.1.1.1
userEntry OBJECT-TYPE
SYNTAX UserEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Description."
INDEX { userIdx }
::= { userTable 1 }
UserEntry ::=
SEQUENCE {
userIdx
Integer32,
userName
Integer32,
userAge
Integer32,
userRowStatus
Integer32
}
-- 1.3.6.1.4.1.85.1.1.1.1
userIdx OBJECT-TYPE
SYNTAX Integer32 (1..1000)
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Description."
::= { userEntry 1 }
-- 1.3.6.1.4.1.85.1.1.1.2
userName OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Description."
::= { userEntry 2 }
-- 1.3.6.1.4.1.85.1.1.1.3
userAge OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Description."
::= { userEntry 3 }
-- 1.3.6.1.4.1.85.1.1.1.4
userRowStatus OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Description."
::= { userEntry 4 }
-- 1.3.6.1.4.1.85.1.3
userGroup OBJECT-GROUP
OBJECTS { userIdx, userName, userAge, userRowStatus }
STATUS current
DESCRIPTION
"Description."
::= { user 3 }
END
--
-- UserTable-MIB.my
--
修改后的MIB文件,有中文注释是修改的地方:
-- UserTable-MIB.my
-- MIB generated by MG-SOFT Visual MIB Builder Version 6.0 Build 88
-- Thursday, August 06, 2020 at 14:12:31
--
UserTable-MIB DEFINITIONS ::= BEGIN
IMPORTS
OBJECT-GROUP
FROM SNMPv2-CONF
enterprises, Integer32, OBJECT-TYPE, MODULE-IDENTITY
FROM SNMPv2-SMI -- 去掉原来的分号
DisplayString, RowStatus -- 增加这一行
FROM SNMPv2-TC; -- 增加这一行
-- 1.3.6.1.4.1.85
myModule MODULE-IDENTITY
LAST-UPDATED "202008071136Z" -- August 07, 2020 at 11:36 GMT
ORGANIZATION
"Organization."
CONTACT-INFO
"Contact-info."
DESCRIPTION
"Description."
::= { enterprises 85 }
--
-- Node definitions
--
-- 1.3.6.1.4.1.85.1
user OBJECT IDENTIFIER ::= { myModule 1 }
-- 1.3.6.1.4.1.85.1.1
userTable OBJECT-TYPE
SYNTAX SEQUENCE OF UserEntry
MAX-ACCESS read-create -- 修改类型为read-create
STATUS current
DESCRIPTION
"Description."
::= { user 1 }
-- 1.3.6.1.4.1.85.1.1.1
userEntry OBJECT-TYPE
SYNTAX UserEntry
MAX-ACCESS read-create -- 修改类型为read-create
STATUS current
DESCRIPTION
"Description."
INDEX { userIdx }
::= { userTable 1 }
UserEntry ::=
SEQUENCE {
userIdx
Integer32,
userName
OCTET STRING,
userAge
Integer32,
userRowStatus
RowStatus -- 修改类型为RowStatus
}
-- 1.3.6.1.4.1.85.1.1.1.1
userIdx OBJECT-TYPE
SYNTAX Integer32 (1..1000)
MAX-ACCESS read-only -- 根据实际业务修改类型
STATUS current
DESCRIPTION
"Description."
::= { userEntry 1 }
-- 1.3.6.1.4.1.85.1.1.1.2
userName OBJECT-TYPE
SYNTAX OCTET STRING
MAX-ACCESS read-write -- 根据实际业务修改类型
STATUS current
DESCRIPTION
"Description."
::= { userEntry 2 }
-- 1.3.6.1.4.1.85.1.1.1.3
userAge OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-write -- 根据实际业务修改类型
STATUS current
DESCRIPTION
"Description."
::= { userEntry 3 }
-- 1.3.6.1.4.1.85.1.1.1.4
userRowStatus OBJECT-TYPE
SYNTAX RowStatus -- 修改为RowStatus
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Description."
::= { userEntry 4 }
-- OBJECT-GROUP可以不要
-- 1.3.6.1.4.1.85.1.3
-- userGroup OBJECT-GROUP
-- OBJECTS { userIdx, userName, userAge, userRowStatus }
-- STATUS current
-- DESCRIPTION
-- "Description."
-- ::= { user 3 }
END
--
-- UserTable-MIB.my
--
二、使用mib2c命令生成.c和.h文件
上传UserTable-MIB.my到linux机器的/usr/local/snmp/share/snmp/mibs目录下
1、使用如下命令查看文件格式是否正确
/usr/local/snmp/bin/snmptranslate -Tp -IR UserTable-MIB::myModule
可以看到userRowStatus节点(也就是RowStatus列)所支持的状态值
2、执行如下命令生成表格文件
env MIBS="+/usr/local/snmp/share/snmp/mibs/UserTable-MIB.my" /usr/local/snmp/bin/mib2c -c mib2c.iterate.conf UserTable-MIB::myModule
以上命令执行完后会生成myModule.h和myModule.c文件
生成的原代码(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_userTable();
}
# Determine the first/last column names
/** Initialize the userTable table by defining its contents and how it's structured */
void
initialize_table_userTable(void)
{
const oid userTable_oid[] = { 1, 3, 6, 1, 4, 1, 85, 1, 1 };
const size_t userTable_oid_len = OID_LENGTH(userTable_oid);
netsnmp_handler_registration *reg;
netsnmp_iterator_info *iinfo;
netsnmp_table_registration_info *table_info;
DEBUGMSGTL(("myModule:init", "initializing table userTable\n"));
reg =
netsnmp_create_handler_registration("userTable", userTable_handler,
userTable_oid,
userTable_oid_len,
HANDLER_CAN_RWRITE);
table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER, /* index: userIdx */
0);
table_info->min_column = COLUMN_USERIDX;
table_info->max_column = COLUMN_USERROWSTATUS;
iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);
iinfo->get_first_data_point = userTable_get_first_data_point;
iinfo->get_next_data_point = userTable_get_next_data_point;
iinfo->table_reginfo = table_info;
netsnmp_register_table_iterator(reg, iinfo);
netsnmp_inject_handler_before(reg,
netsnmp_get_cache_handler
(USERTABLE_TIMEOUT, userTable_load,
userTable_free, userTable_oid,
userTable_oid_len),
TABLE_ITERATOR_NAME);
/*
* Initialise the contents of the table here
*/
}
/*
* Typical data structure for a row entry
*/
struct userTable_entry {
/*
* Index values
*/
long userIdx;
/*
* Column values
*/
long userIdx;
char userName[NNN];
size_t userName_len;
char old_userName[NNN];
size_t old_userName_len;
long userAge;
long old_userAge;
long userRowStatus;
/*
* Illustrate using a simple linked list
*/
int valid;
struct userTable_entry *next;
};
struct userTable_entry *userTable_head;
/*
* create a new row in the (unsorted) table
*/
struct userTable_entry *
userTable_createEntry(long userIdx,)
{
struct userTable_entry *entry;
entry = SNMP_MALLOC_TYPEDEF(struct userTable_entry);
if (!entry)
return NULL;
entry->userIdx = userIdx;
entry->next = userTable_head;
userTable_head = entry;
return entry;
}
/*
* remove a row from the table
*/
void
userTable_removeEntry(struct userTable_entry *entry)
{
struct userTable_entry *ptr, *prev;
if (!entry)
return; /* Nothing to remove */
for (ptr = userTable_head, prev = NULL;
ptr != NULL; prev = ptr, ptr = ptr->next) {
if (ptr == entry)
break;
}
if (!ptr)
return; /* Can't find it */
if (prev == NULL)
userTable_head = ptr->next;
else
prev->next = ptr->next;
SNMP_FREE(entry); /* XXX - release any other internal resources */
}
/*
* Example cache handling - set up linked list from a suitable file
*/
int
userTable_load(netsnmp_cache * cache, void *vmagic)
{
FILE *fp;
struct userTable_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/userTable", "r");
if (!fp) {
return -1;
}
while (fgets(buf, STRMAX, fp)) {
this = SNMP_MALLOC_TYPEDEF(struct userTable_entry);
/*
* XXX - Unpick 'buf' to extract the individual field values
* and then populate the 'this' data structure with them
*/
this->next = userTable_head;
userTable_head = this; /* Iterate helper is fine with unordered lists! */
}
fclose(fp);
return 0; /* OK */
}
void
userTable_free(netsnmp_cache * cache, void *vmagic)
{
struct userTable_entry *this, *that;
for (this = userTable_head; this; this = that) {
that = this->next;
SNMP_FREE(this); /* XXX - release any other internal resources */
}
userTable_head = NULL;
}
/*
* Example iterator hook routines - using 'get_next' to do most of the work
*/
netsnmp_variable_list *
userTable_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 = userTable_head;
return userTable_get_next_data_point(my_loop_context, my_data_context,
put_index_data, mydata);
}
netsnmp_variable_list *
userTable_get_next_data_point(void **my_loop_context,
void **my_data_context,
netsnmp_variable_list * put_index_data,
netsnmp_iterator_info *mydata)
{
struct userTable_entry *entry =
(struct userTable_entry *) *my_loop_context;
netsnmp_variable_list *idx = put_index_data;
if (entry) {
snmp_set_var_typed_integer(idx, ASN_INTEGER, entry->userIdx);
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 userTable table */
int
userTable_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 userTable_entry *table_entry;
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 userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERIDX:
if (!table_entry) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
table_entry->userIdx);
break;
case COLUMN_USERNAME:
if (!table_entry) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
table_entry->userName,
table_entry->userName_len);
break;
case COLUMN_USERAGE:
if (!table_entry) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
table_entry->userAge);
break;
case COLUMN_USERROWSTATUS:
if (!table_entry) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
table_entry->userRowStatus);
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 userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERNAME:
/*
* or possibly 'netsnmp_check_vb_type_and_size'
*/
ret =
netsnmp_check_vb_type_and_max_size(request->requestvb,
ASN_OCTET_STR,
sizeof(table_entry->
userName));
if (ret != SNMP_ERR_NOERROR) {
netsnmp_set_request_error(reqinfo, request, ret);
return SNMP_ERR_NOERROR;
}
break;
case COLUMN_USERAGE:
/*
* 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_USERROWSTATUS:
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 userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERROWSTATUS:
switch (*request->requestvb->val.integer) {
case RS_CREATEANDGO:
case RS_CREATEANDWAIT:
table_row =
userTable_createEntry(,
*table_info->indexes->val.
integer);
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 userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERROWSTATUS:
switch (*request->requestvb->val.integer) {
case RS_CREATEANDGO:
case RS_CREATEANDWAIT:
if (table_entry && !table_entry->valid) {
userTable_removeEntry(table_data, table_row);
}
}
}
}
break;
case MODE_SET_ACTION:
for (request = requests; request; request = request->next) {
table_entry = (struct userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERNAME:
memcpy(table_entry->old_userName,
table_entry->userName,
sizeof(table_entry->userName));
table_entry->old_userName_len = table_entry->userName_len;
memset(table_entry->userName, 0,
sizeof(table_entry->userName));
memcpy(table_entry->userName,
request->requestvb->val.string,
request->requestvb->val_len);
table_entry->userName_len = request->requestvb->val_len;
break;
case COLUMN_USERAGE:
table_entry->old_userAge = table_entry->userAge;
table_entry->userAge = *request->requestvb->val.integer;
break;
}
}
/*
* Check the internal consistency of an active row
*/
for (request = requests; request; request = request->next) {
table_entry = (struct userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERROWSTATUS:
switch (*request->requestvb->val.integer) {
case RS_ACTIVE:
case RS_CREATEANDGO:
if ( /* XXX */ ) {
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 userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERNAME:
memcpy(table_entry->userName,
table_entry->old_userName,
sizeof(table_entry->userName));
memset(table_entry->old_userName, 0,
sizeof(table_entry->userName));
table_entry->userName_len = table_entry->old_userName_len;
break;
case COLUMN_USERAGE:
table_entry->userAge = table_entry->old_userAge;
table_entry->old_userAge = 0;
break;
case COLUMN_USERROWSTATUS:
switch (*request->requestvb->val.integer) {
case RS_CREATEANDGO:
case RS_CREATEANDWAIT:
if (table_entry && !table_entry->valid) {
userTable_removeEntry(table_data, table_row);
}
}
break;
}
}
break;
case MODE_SET_COMMIT:
for (request = requests; request; request = request->next) {
table_entry = (struct userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERROWSTATUS:
switch (*request->requestvb->val.integer) {
case RS_CREATEANDGO:
table_entry->valid = 1;
/*
* Fall-through
*/
case RS_ACTIVE:
table_entry->userRowStatus = RS_ACTIVE;
break;
case RS_CREATEANDWAIT:
table_entry->valid = 1;
/*
* Fall-through
*/
case RS_NOTINSERVICE:
table_entry->userRowStatus = RS_NOTINSERVICE;
break;
case RS_DESTROY:
userTable_removeEntry(table_data, table_row);
}
}
}
break;
}
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_userTable();
}
// 注释下面这行
// # Determine the first/last column names
/** Initialize the userTable table by defining its contents and how it's structured */
void
initialize_table_userTable(void)
{
const oid userTable_oid[] = { 1, 3, 6, 1, 4, 1, 85, 1, 1 };
const size_t userTable_oid_len = OID_LENGTH(userTable_oid);
netsnmp_handler_registration *reg;
netsnmp_iterator_info *iinfo;
netsnmp_table_registration_info *table_info;
DEBUGMSGTL(("myModule:init", "initializing table userTable\n"));
reg =
netsnmp_create_handler_registration("userTable", userTable_handler,
userTable_oid,
userTable_oid_len,
HANDLER_CAN_RWRITE);
table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER, /* index: userIdx */
0);
table_info->min_column = COLUMN_USERIDX;
table_info->max_column = COLUMN_USERROWSTATUS;
iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);
iinfo->get_first_data_point = userTable_get_first_data_point;
iinfo->get_next_data_point = userTable_get_next_data_point;
iinfo->table_reginfo = table_info;
netsnmp_register_table_iterator(reg, iinfo);
netsnmp_inject_handler_before(reg,
netsnmp_get_cache_handler
(USERTABLE_TIMEOUT, userTable_load,
userTable_free, userTable_oid,
userTable_oid_len),
TABLE_ITERATOR_NAME);
/*
* Initialise the contents of the table here
*/
}
#define NNN 256 //定义这个宏,下面这个结构体用到
/*
* Typical data structure for a row entry
*/
struct userTable_entry {
/*
* Index values
*/
long userIdx;
/*
* Column values
*/
// long userIdx; //注释掉,上面已经定义了
char userName[NNN];
size_t userName_len;
char old_userName[NNN];
size_t old_userName_len;
long userAge;
long old_userAge;
long userRowStatus;
/*
* Illustrate using a simple linked list
*/
int valid;
struct userTable_entry *next;
};
struct userTable_entry *userTable_head;
/*
* create a new row in the (unsorted) table
*/
//补全这个函数的参数,其实就是表格中那四列的内容
//这个函数就是添加一行数据的函数,RowStatus列不传也可以,程序内部会自动处理
struct userTable_entry *
userTable_createEntry(long userIdx,char *userName ,size_t userName_len,long userAge)
{
struct userTable_entry *entry;
entry = SNMP_MALLOC_TYPEDEF(struct userTable_entry);
if (!entry)
return NULL;
entry->userIdx = userIdx;
snprintf(entry->userName, sizeof(entry->userName), "%s", userName); //将userName数据赋给结构体
entry->userName_len = userName_len; //将userName_len数据赋给结构体
entry->userAge = userAge; //将userAge数据赋值给结构体
entry->next = userTable_head;
userTable_head = entry;
return entry;
}
/*
* remove a row from the table
*/
void
userTable_removeEntry(struct userTable_entry *entry)
{
struct userTable_entry *ptr, *prev;
if (!entry)
return; /* Nothing to remove */
for (ptr = userTable_head, prev = NULL;
ptr != NULL; prev = ptr, ptr = ptr->next) {
if (ptr == entry)
break;
}
if (!ptr)
return; /* Can't find it */
if (prev == NULL)
userTable_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
userTable_load(netsnmp_cache * cache, void *vmagic)
{
FILE *fp;
struct userTable_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/userTable", "r");
if (!fp) {
return -1;
}
while (fgets(buf, STRMAX, fp)) {
this = SNMP_MALLOC_TYPEDEF(struct userTable_entry);
/*
* XXX - Unpick 'buf' to extract the individual field values
* and then populate the 'this' data structure with them
*/
this->next = userTable_head;
userTable_head = this; /* Iterate helper is fine with unordered lists! */
}
fclose(fp);
return 0; /* OK */
}
void
userTable_free(netsnmp_cache * cache, void *vmagic)
{
struct userTable_entry *this, *that;
for (this = userTable_head; this; this = that) {
that = this->next;
SNMP_FREE(this); /* XXX - release any other internal resources */
}
userTable_head = NULL;
}
/*
* Example iterator hook routines - using 'get_next' to do most of the work
*/
netsnmp_variable_list *
userTable_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 = userTable_head;
return userTable_get_next_data_point(my_loop_context, my_data_context,
put_index_data, mydata);
}
netsnmp_variable_list *
userTable_get_next_data_point(void **my_loop_context,
void **my_data_context,
netsnmp_variable_list * put_index_data,
netsnmp_iterator_info *mydata)
{
struct userTable_entry *entry =
(struct userTable_entry *) *my_loop_context;
netsnmp_variable_list *idx = put_index_data;
if (entry) {
snmp_set_var_typed_integer(idx, ASN_INTEGER, entry->userIdx);
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 userTable table */
int
userTable_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 userTable_entry *table_entry;
struct userTable_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 userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERIDX:
if (!table_entry) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
table_entry->userIdx);
break;
case COLUMN_USERNAME:
if (!table_entry) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
table_entry->userName,
table_entry->userName_len);
break;
case COLUMN_USERAGE:
if (!table_entry) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
table_entry->userAge);
break;
case COLUMN_USERROWSTATUS:
if (!table_entry) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
table_entry->userRowStatus);
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 userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERNAME:
/*
* or possibly 'netsnmp_check_vb_type_and_size'
*/
ret =
netsnmp_check_vb_type_and_max_size(request->requestvb,
ASN_OCTET_STR,
sizeof(table_entry->
userName));
if (ret != SNMP_ERR_NOERROR) {
netsnmp_set_request_error(reqinfo, request, ret);
return SNMP_ERR_NOERROR;
}
break;
case COLUMN_USERAGE:
/*
* 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_USERROWSTATUS:
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 userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERROWSTATUS:
switch (*request->requestvb->val.integer) {
case RS_CREATEANDGO:
case RS_CREATEANDWAIT:
table_row =
userTable_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 userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERROWSTATUS:
switch (*request->requestvb->val.integer) {
case RS_CREATEANDGO:
case RS_CREATEANDWAIT:
if (table_entry && !table_entry->valid) {
userTable_removeEntry(table_row); //多传了table_data参数,删除
}
}
}
}
break;
case MODE_SET_ACTION:
for (request = requests; request; request = request->next) {
table_entry = (struct userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERNAME:
memcpy(table_entry->old_userName,
table_entry->userName,
sizeof(table_entry->userName));
table_entry->old_userName_len = table_entry->userName_len;
memset(table_entry->userName, 0,
sizeof(table_entry->userName));
memcpy(table_entry->userName,
request->requestvb->val.string,
request->requestvb->val_len);
table_entry->userName_len = request->requestvb->val_len;
break;
case COLUMN_USERAGE:
table_entry->old_userAge = table_entry->userAge;
table_entry->userAge = *request->requestvb->val.integer;
break;
}
}
/*
* Check the internal consistency of an active row
*/
for (request = requests; request; request = request->next) {
table_entry = (struct userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERROWSTATUS:
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 userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERNAME:
memcpy(table_entry->userName,
table_entry->old_userName,
sizeof(table_entry->userName));
memset(table_entry->old_userName, 0,
sizeof(table_entry->userName));
table_entry->userName_len = table_entry->old_userName_len;
break;
case COLUMN_USERAGE:
table_entry->userAge = table_entry->old_userAge;
table_entry->old_userAge = 0;
break;
case COLUMN_USERROWSTATUS:
switch (*request->requestvb->val.integer) {
case RS_CREATEANDGO:
case RS_CREATEANDWAIT:
if (table_entry && !table_entry->valid) {
userTable_removeEntry(table_row); //多传了table_data参数,删除
}
}
break;
}
}
break;
case MODE_SET_COMMIT:
for (request = requests; request; request = request->next) {
table_entry = (struct userTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);
switch (table_info->colnum) {
case COLUMN_USERROWSTATUS:
switch (*request->requestvb->val.integer) {
case RS_CREATEANDGO:
table_entry->valid = 1;
/*
* Fall-through
*/
case RS_ACTIVE:
table_entry->userRowStatus = RS_ACTIVE;
break;
case RS_CREATEANDWAIT:
table_entry->valid = 1;
/*
* Fall-through
*/
case RS_NOTINSERVICE:
table_entry->userRowStatus = RS_NOTINSERVICE;
break;
case RS_DESTROY:
userTable_removeEntry(table_entry); //修改table_row为table_entry,否则删除行不成功, 多传了table_data参数,删除
}
}
}
break;
}
return SNMP_ERR_NOERROR;
}
三、载入自定义的MIB库
1、将myModule.h 和修改后的myModule.c文件复制到linux机器的net-snmp-5.7.1/agent/mibgroup/目录下
2、如果snmp服务在运行,停止snmp服务
3、在/root/net-snmp-5.7.1目录下依次执行下面3个命令编译安装
./configure --prefix=/usr/local/snmp --with-mib-modules=“myModule”
make && make install
四、测试
1、执行/usr/local/snmp/sbin/snmpd -c /usr/local/snmp/etc/snmpd.conf 命令启动snmp服务
2、执行/usr/local/snmp/bin/snmpwalk -v 2c -c public localhost 1.3.6.1.4.1.85.1.1查看表格内容,可以看到表里什么都没有
3、添加第一行数据:/usr/local/snmp/bin/snmpset -v 2c -c public localhost 1.3.6.1.4.1.85.1.1.1.4.1 i 4
这个命令表示对表的第一行的第三列设置值为4,因为第三列为RowStatus类型,所以系统会创建这一行
(表中原本是没有第一行的,只要对第一行的RowStatus列写入4就可以创建这一行)
4、修改第一行数据中的userName字段:/usr/local/snmp/bin/snmpset -v 2c -c public localhost 1.3.6.1.4.1.85.1.1.1.2.1 s harara
5、修改第一行数据中的userAge字段:/usr/local/snmp/bin/snmpset -v 2c -c public localhost 1.3.6.1.4.1.85.1.1.1.3.1 i 24
6、删除第1行,对第1行的第4列写入6即可:/usr/local/snmp/bin/snmpset -v 2c -c public localhost 1.3.6.1.4.1.85.1.1.1.4.1 i 6