zoukankan      html  css  js  c++  java
  • 【snmp】net-snmp添加自定义MIB(表格)

    安装net-snmp见:【snmp】centos6.5安装和配置snmp5.7.1

    net-snmp添加自定义MIB(标量):【snmp】net-snmp添加自定义MIB(标量) 

    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
    --
    View Code

    修改后的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.hmyModule.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
    "));
    
        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)
    ",
                    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;
    }
    View Code

    需要对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
    "));
    
        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)
    ",
                    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

  • 相关阅读:
    u-boot编译
    本地套接字
    内核线程
    长度为0数组
    Ubuntu安装KScope
    Python基础-运算符
    如何有效地记录 Java SQL 日志?
    解谜谷歌 DevOps:什么特质可以打造世界级可靠系统?
    如何打造前所未有的服务器端监控体验?
    趣味Python入门(一):初识Python
  • 原文地址:https://www.cnblogs.com/kiko2014551511/p/13370768.html
Copyright © 2011-2022 走看看