SNMP整理

五迷三道 提交于 2019-12-15 10:02:51
  1. snmp简介
    snmp简单网络设备管理协议,用于管理网络IP节点中的各种网络设备如交换机、路由器、防火墙、审计等。
    详细介绍可参考百度百科:https://baike.baidu.com/item/%E7%AE%80%E5%8D%95%E7%BD%91%E7%BB%9C%E7%AE%A1%E7%90%86%E5%8D%8F%E8%AE%AE/2986113?fromtitle=SNMP&fromid=133378&fr=aladdin

  2. snmp获取节点信息
    snmp通过oid节点获取到相应设备提供的信息,oid类似地址的概念,是snmp官方定义的一种寻址标准。
    详情可参考:https://www.alvestrand.no/objectid/1.3.6.1.html

  3. MIB
    mib库是对snmp网络设备提供服务节点的一个描述,通过mib浏览器加载MIB库就能读取到相应设备的节点信息。MIB可以手动编写,也可以使用snmp开发套件中的mib-builder。

    **保存的文件名如图中module-name一致。
    加粗样式**新建的mib库需要使用mib compiler编译后供mib browser使用

--
-- VENUS-DAS-MIB.txt
-- MIB generated by MG-SOFT Visual MIB Builder Version 6.0  Build 88
-- Tuesday, December 10, 2019 at 20:31:39
--

--  VENUS-DAS-MIB.txt
-- MIB generated by MG-SOFT Visual MIB Builder Version 6.0  Build 88
-- Sunday, December 08, 2019 at 20:29:10
-- 
--  VENUS-DAS-MIB.txt
-- MIB generated by MG-SOFT Visual MIB Builder Version 6.0  Build 88
-- Friday, December 06, 2019 at 23:26:35
-- 
--  TSET-SCALAR-MIB.txt
-- MIB generated by MG-SOFT Visual MIB Builder Version 6.0  Build 88
-- Friday, December 06, 2019 at 21:36:16
-- 

	VENUS-DAS-MIB DEFINITIONS ::= BEGIN
 
		IMPORTS
			enterprises, Integer32, OBJECT-TYPE			
				FROM SNMPv2-SMI;
	
	
--
-- Node definitions
--
	
--  Node definitions
-- 
-- Node definitions
-- 
-- Node definitions
-- 
-- 1.3.6.1.4.1.15227
-- 1.3.6.1.4.1.15227
-- 1.3.6.1.4.1.15227
		-- 1.3.6.1.4.1.15227
		venusDasRoot OBJECT IDENTIFIER ::= { enterprises 15227 }

		
--    1.3.6.1.4.1.15227.1
-- 1.3.6.1.4.1.15227.1
-- 1.3.6.1.4.1.15227.1
		-- 1.3.6.1.4.1.15227.1
		cpuCount OBJECT-TYPE
			SYNTAX Integer32 (0..16)
			MAX-ACCESS read-only
			STATUS current
			DESCRIPTION
				"表示CPU总核心数"
			::= { venusDasRoot 1 }

		
--    1.3.6.1.4.1.15227.2
-- 1.3.6.1.4.1.15227.2
-- 1.3.6.1.4.1.15227.2
		-- 1.3.6.1.4.1.15227.2
		cpuUsage OBJECT-TYPE
			SYNTAX Integer32 (0..100)
			MAX-ACCESS read-only
			STATUS current
			DESCRIPTION
				"CPU使用率"
			::= { venusDasRoot 2 }

		
--   1.3.6.1.4.1.15227.3
-- 1.3.6.1.4.1.15227.3
		-- 1.3.6.1.4.1.15227.3
		diskTotal OBJECT-TYPE
			SYNTAX Integer32 (0..32000000)
			MAX-ACCESS read-only
			STATUS current
			DESCRIPTION
				"硬盘总容量
				单位:M
				最大值:32T"
			::= { venusDasRoot 3 }

		
--   1.3.6.1.4.1.15227.4
-- 1.3.6.1.4.1.15227.4
		-- 1.3.6.1.4.1.15227.4
		diskUse OBJECT-TYPE
			SYNTAX Integer32 (0..32000000)
			MAX-ACCESS read-only
			STATUS current
			DESCRIPTION
				"硬盘已使用容量
				单位:M
				最大值:32T"
			::= { venusDasRoot 4 }

		
--   1.3.6.1.4.1.15227.5
-- 1.3.6.1.4.1.15227.5
		-- 1.3.6.1.4.1.15227.5
		diskUsage OBJECT-TYPE
			SYNTAX Integer32 (0..100)
			MAX-ACCESS read-only
			STATUS current
			DESCRIPTION
				"硬盘使用率"
			::= { venusDasRoot 5 }

		
--   1.3.6.1.4.1.15227.6
-- 1.3.6.1.4.1.15227.6
		-- 1.3.6.1.4.1.15227.6
		memTotal OBJECT-TYPE
			SYNTAX Integer32 (0..32000000)
			MAX-ACCESS read-only
			STATUS current
			DESCRIPTION
				"内存总大小
				单位:KB
				最大值:32G"
			::= { venusDasRoot 6 }

		
--   1.3.6.1.4.1.15227.7
-- 1.3.6.1.4.1.15227.7
		-- 1.3.6.1.4.1.15227.7
		memUse OBJECT-TYPE
			SYNTAX Integer32 (0..32000000)
			MAX-ACCESS read-only
			STATUS current
			DESCRIPTION
				"内存已使用大小
				单位:KB
				最大值:32G"
			::= { venusDasRoot 7 }

		
--   1.3.6.1.4.1.15227.8
-- 1.3.6.1.4.1.15227.8
		-- 1.3.6.1.4.1.15227.8
		memUsage OBJECT-TYPE
			SYNTAX Integer32 (0..100)
			MAX-ACCESS read-only
			STATUS current
			DESCRIPTION
				"内存使用率"
			::= { venusDasRoot 8 }

		
	
	END

--
-- VENUS-DAS-MIB.txt
--

4.安装net-snmp

下载net-snmp源代码,https://github.com/haad/net-snmp

unzip 解压文件

依次执行如下命令执行:
./configure --prefix=/install_path 生成makefile 并且配置安装目录
make 编译
make install 安装到系统,可以在install_path 找到安装的文件。

拷贝当前目录中的EXAMPLE.conf 到/install_path/share/snmp/snmpd.conf

修改:agentAddress udp:127.0.0.1:161
为:agentAddress udp:161 允许所有地址可访问
修改:rocommunity public default -V systemonly
为:rocommunity public default 允许访问所有资源
注释掉:trapsink localhost public
去掉注释:#trap2sink localhost public

添加环境变量后,snmpd 即可启动snmp服务
netstat -anp | grep 161 查看端口监听是否正常

snmpwalk -v 2c -c public localhost 1.3.6.1.4 即可查看snmp服务返回的系统信息

  1. 扩展mib库

    将写好的VENUS-DAS-MIB.txt放在/install_path/share/snmp/mibs

    使用snmptranslate -Tp -IR VENUS-DAS-MIB::venusDasRoot 验证是否能获取到节点信息

    使用env MIBS="+/install_path/share/snmp/mibs/VENUS-DAS-MIB.txt" mib2c -c mib2c.scalar.conf venusDasRoot 生成需要的c文件和头文件

venusDasRoot.c

/*
 * Note: this file originally auto-generated by mib2c
 * using mib2c.scalar.conf
 */

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "venusDasRoot.h"

/** Initializes the venusDasRoot module */
void
init_venusDasRoot(void)
{
    const oid cpuCount_oid[] = { 1,3,6,1,4,1,15227,1 };
    const oid cpuUsage_oid[] = { 1,3,6,1,4,1,15227,2 };
    const oid diskTotal_oid[] = { 1,3,6,1,4,1,15227,3 };
    const oid diskUse_oid[] = { 1,3,6,1,4,1,15227,4 };
    const oid diskUsage_oid[] = { 1,3,6,1,4,1,15227,5 };
    const oid memTotal_oid[] = { 1,3,6,1,4,1,15227,6 };
    const oid memUse_oid[] = { 1,3,6,1,4,1,15227,7 };
    const oid memUsage_oid[] = { 1,3,6,1,4,1,15227,8 };

  DEBUGMSGTL(("venusDasRoot", "Initializing\n"));

    netsnmp_register_scalar(
        netsnmp_create_handler_registration("cpuCount", handle_cpuCount,
                               cpuCount_oid, OID_LENGTH(cpuCount_oid),
                               HANDLER_CAN_RONLY
        ));
    netsnmp_register_scalar(
        netsnmp_create_handler_registration("cpuUsage", handle_cpuUsage,
                               cpuUsage_oid, OID_LENGTH(cpuUsage_oid),
                               HANDLER_CAN_RONLY
        ));
    netsnmp_register_scalar(
        netsnmp_create_handler_registration("diskTotal", handle_diskTotal,
                               diskTotal_oid, OID_LENGTH(diskTotal_oid),
                               HANDLER_CAN_RONLY
        ));
    netsnmp_register_scalar(
        netsnmp_create_handler_registration("diskUse", handle_diskUse,
                               diskUse_oid, OID_LENGTH(diskUse_oid),
                               HANDLER_CAN_RONLY
        ));
    netsnmp_register_scalar(
        netsnmp_create_handler_registration("diskUsage", handle_diskUsage,
                               diskUsage_oid, OID_LENGTH(diskUsage_oid),
                               HANDLER_CAN_RONLY
        ));
    netsnmp_register_scalar(
        netsnmp_create_handler_registration("memTotal", handle_memTotal,
                               memTotal_oid, OID_LENGTH(memTotal_oid),
                               HANDLER_CAN_RONLY
        ));
    netsnmp_register_scalar(
        netsnmp_create_handler_registration("memUse", handle_memUse,
                               memUse_oid, OID_LENGTH(memUse_oid),
                               HANDLER_CAN_RONLY
        ));
    netsnmp_register_scalar(
        netsnmp_create_handler_registration("memUsage", handle_memUsage,
                               memUsage_oid, OID_LENGTH(memUsage_oid),
                               HANDLER_CAN_RONLY
        ));
}

int
handle_cpuCount(netsnmp_mib_handler *handler,
                          netsnmp_handler_registration *reginfo,
                          netsnmp_agent_request_info   *reqinfo,
                          netsnmp_request_info         *requests)
{
    /* 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_INTEGER,
                                     /* XXX: a pointer to the scalar's data */,
                                     /* XXX: the length of the data in bytes */);
            break;


        default:
            /* we should never get here, so this is a really bad error */
            snmp_log(LOG_ERR, "unknown mode (%d) in handle_cpuCount\n", reqinfo->mode );
            return SNMP_ERR_GENERR;
    }

    return SNMP_ERR_NOERROR;
}
int
handle_cpuUsage(netsnmp_mib_handler *handler,
                          netsnmp_handler_registration *reginfo,
                          netsnmp_agent_request_info   *reqinfo,
                          netsnmp_request_info         *requests)
{
    /* 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_INTEGER,
                                     /* XXX: a pointer to the scalar's data */,
                                     /* XXX: the length of the data in bytes */);
            break;


        default:
            /* we should never get here, so this is a really bad error */
            snmp_log(LOG_ERR, "unknown mode (%d) in handle_cpuUsage\n", reqinfo->mode );
            return SNMP_ERR_GENERR;
    }

    return SNMP_ERR_NOERROR;
}
int
handle_diskTotal(netsnmp_mib_handler *handler,
                          netsnmp_handler_registration *reginfo,
                          netsnmp_agent_request_info   *reqinfo,
                          netsnmp_request_info         *requests)
{
    /* 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_INTEGER,
                                     /* XXX: a pointer to the scalar's data */,
                                     /* XXX: the length of the data in bytes */);
            break;


        default:
            /* we should never get here, so this is a really bad error */
            snmp_log(LOG_ERR, "unknown mode (%d) in handle_diskTotal\n", reqinfo->mode );
            return SNMP_ERR_GENERR;
    }

    return SNMP_ERR_NOERROR;
}
int
handle_diskUse(netsnmp_mib_handler *handler,
                          netsnmp_handler_registration *reginfo,
                          netsnmp_agent_request_info   *reqinfo,
                          netsnmp_request_info         *requests)
{
    /* 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_INTEGER,
                                     /* XXX: a pointer to the scalar's data */,
                                     /* XXX: the length of the data in bytes */);
            break;


        default:
            /* we should never get here, so this is a really bad error */
            snmp_log(LOG_ERR, "unknown mode (%d) in handle_diskUse\n", reqinfo->mode );
            return SNMP_ERR_GENERR;
    }

    return SNMP_ERR_NOERROR;
}
int
handle_diskUsage(netsnmp_mib_handler *handler,
                          netsnmp_handler_registration *reginfo,
                          netsnmp_agent_request_info   *reqinfo,
                          netsnmp_request_info         *requests)
{
    /* 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_INTEGER,
                                     /* XXX: a pointer to the scalar's data */,
                                     /* XXX: the length of the data in bytes */);
            break;


        default:
            /* we should never get here, so this is a really bad error */
            snmp_log(LOG_ERR, "unknown mode (%d) in handle_diskUsage\n", reqinfo->mode );
            return SNMP_ERR_GENERR;
    }

    return SNMP_ERR_NOERROR;
}
int
handle_memTotal(netsnmp_mib_handler *handler,
                          netsnmp_handler_registration *reginfo,
                          netsnmp_agent_request_info   *reqinfo,
                          netsnmp_request_info         *requests)
{
    /* 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_INTEGER,
                                     /* XXX: a pointer to the scalar's data */,
                                     /* XXX: the length of the data in bytes */);
            break;


        default:
            /* we should never get here, so this is a really bad error */
            snmp_log(LOG_ERR, "unknown mode (%d) in handle_memTotal\n", reqinfo->mode );
            return SNMP_ERR_GENERR;
    }

    return SNMP_ERR_NOERROR;
}
int
handle_memUse(netsnmp_mib_handler *handler,
                          netsnmp_handler_registration *reginfo,
                          netsnmp_agent_request_info   *reqinfo,
                          netsnmp_request_info         *requests)
{
    /* 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_INTEGER,
                                     /* XXX: a pointer to the scalar's data */,
                                     /* XXX: the length of the data in bytes */);
            break;


        default:
            /* we should never get here, so this is a really bad error */
            snmp_log(LOG_ERR, "unknown mode (%d) in handle_memUse\n", reqinfo->mode );
            return SNMP_ERR_GENERR;
    }

    return SNMP_ERR_NOERROR;
}
int
handle_memUsage(netsnmp_mib_handler *handler,
                          netsnmp_handler_registration *reginfo,
                          netsnmp_agent_request_info   *reqinfo,
                          netsnmp_request_info         *requests)
{
    /* 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_INTEGER,
                                     /* XXX: a pointer to the scalar's data */,
                                     /* XXX: the length of the data in bytes */);
            break;


        default:
            /* we should never get here, so this is a really bad error */
            snmp_log(LOG_ERR, "unknown mode (%d) in handle_memUsage\n", reqinfo->mode );
            return SNMP_ERR_GENERR;
    }

    return SNMP_ERR_NOERROR;
}

venusDasRoot.h

/*
 * Note: this file originally auto-generated by mib2c
 * using mib2c.scalar.conf
 */
#ifndef VENUSDASROOT_H
#define VENUSDASROOT_H

/* function declarations */
void init_venusDasRoot(void);
Netsnmp_Node_Handler handle_cpuCount;
Netsnmp_Node_Handler handle_cpuUsage;
Netsnmp_Node_Handler handle_diskTotal;
Netsnmp_Node_Handler handle_diskUse;
Netsnmp_Node_Handler handle_diskUsage;
Netsnmp_Node_Handler handle_memTotal;
Netsnmp_Node_Handler handle_memUse;
Netsnmp_Node_Handler handle_memUsage;

#endif /* VENUSDASROOT_H */

并且修改代码中类似以下代码的位置,赋值自己想要返回的东西。
/* XXX: a pointer to the scalar’s data /,
/
XXX: the length of the data in bytes */

最后将代码添加到net-snmp源代码的 /agent/mibgroup/路径下
执行 ./configure --perfix=/install_path --with-mib-modules=“venusDasRoot”
添加自定义模块

make && make install

最后启动snmpd

使用snmpwalk -c public -v 2c localhost 1.3.6.1.4.1.15227
即可以获得自定义的处理信息

总结说明:
研究此问题的起因是修改snmp的返回值类型,修改string为integer类型。
通过snmpd.conf extend 脚本的形式返回值永远为string类型,脚本的退出
状态为整形,但是退出值存在0-255的限定范围。

	故而采用net-snmp 在snmp中注册回调函数,实现返回值为integer类型。
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!