基于net-snmp的代理端及管理端开发手册

Net-snmp 代理端与管理端拓展开发手册

1、snmp 工作原理介绍
在这里插入图片描述

网络管理包括对硬件、软件和人力的使用、综合与协调。SNMP中的管理程序和代理程序是按照客户服务器的方式安排工作。在网络管理领域, 管理对象和被管理对象需要分别执行两套程序来完成该任务—管理程序和代理程序。在管理者主机上运行管理程序,一般作为客户端,在被管对象上运行代理程序,一般是服务器。在被管对象上运行的服务器进程不断监听来自管理站的SNMP客户程序的请求(术语一般是get或者set命令),如果请求合法有效,那么管理进程则立即返回管理站所需的信息,或者执行某个动作(设置参数等),就这样完成双方的通信。
2、snmp协议发展历程
简单网络管理协议(SNMP) 是专门设计用于在 IP 网络管理网络节点的一种标准协议,它是一种应用层协议,使用UDP(用户数据报协议)作为第四层协议(传输协议),进行无连接操作。
SNMP目前共有v1,v2,v3这三个版本:
SNMP v1是SNMP协议的最初版本,不过依然是众多厂家实现SNMP基本方式。
SNMP v2通常被指是基于community的SNMP V2。Community实质上就是密码(目前)。
SNMP v3 是最新版本的SNMP。它对网络管理最大的贡献在于其安全性。增加了对认证和密文传输的支持。、
3、Net-snmp与snmp的关系
Snmp是一个协议,用来管理网络设备,Net-snmp是snmp协议的一个实现,而且Net-snmp被使用的范围较广,本文将基于net-snmp的基础上进行代理端与管理端的拓展开发。
4、NET-SNMP源码安装
4.1、net-snmp源码安装
通过https://sourceforge.net/projects/net-snmp/files/net-snmp/找到一个稳定的发布版本。这里选择5,8版如下图所示
在这里插入图片描述

点击5.8得下图
在这里插入图片描述

通过点击下载将得到的net-snmp-5.8.tar.gz放到linux环境操作系统中,使用下面指令进行解压
tar -zxvf net-snmp-5.8.tar.gz
得如下图所示
Net-snmp-5.8为解压后的文件夹名
在这里插入图片描述

进入该文件夹,可以看到如下图内容
在这里插入图片描述

正常情况下直接依次执行下列命令
./confiugre //检查编译条件及环境阶段及主机环境
Make //编译阶段
Make install //安装阶段 将相关可执行程序,动态库及头文件及配置文件放到系统目录

备注:./confiugre出现的错误
错误1:configure: error: cannot guess build type; you must specify one
说明:该错误表示在无法自动检查出当前系统的编译环境,此时需要手动给出当前系统的编译环境。
解决方法:
例如通过gcc -v或者uname -a可以看出当前gcc的版本及主机环境,,如下图
在这里插入图片描述

可以看出当前的编译环境为arm-linux(及arm架构的cpu,linux内核的操作系统);
这里需要执行:./configure --build=arm-linux (–build表示手动指定当前的编译环境)。
备注:make过程出现的错误
错误1:提示cannot find -lxxx (xxx):这种况下一般表示当在编译阶段没有找到libxxx.so依赖库。
解决方法:
1,先通过 find / -name libxxx.so* 在当前系统查找是否有该动态库,如果有,则通过ln 通过为该动态库建立个软连接,将软连接放到gcc编译阶段能够搜索到的路径下。
2,如果没有查找到该动态库,则需要通过在线或者离线安装所需要的动态库文件到指定路径。
错误2:出现一些c语言中的语法问题,比如未定义的变量,等问题。
解决方法:这种情况下问题一般在于./configure 过程出现的错误,此时需要开发人员认真查看./configure过程中的打印,找到问题的原因,然后根据原因来找到解决问题的方法。

4.2、编译后源码部分目录讲解
Make instal 之后系统中会多出如下几个目录
/usr/local/sbin/ :存放snmpd,mib2c,snmpget.snmptranslate,snmpwalk,等相关指令的地方.关于这些指令的使用可以参照《深入理解Net-snmp》6.3节
/usr/local/share/snmp 存放snmpd等程序所需配置文件的地方。

/usr/local/share/snmp/mibs 存放mib文件的地方,关于mib文件的编写请查看ANS1相关规范及《深入理解Net-snmp》书籍中的相关内容

下面对编译后的源码目录进行介绍:
Agent:里面主要包含snmpd代理端程序及子代理开发所需要的动态库
Apps:里面主要包含各种管理端各种工具(可供脚本方式开发管理端)及各种开发测试工具,这些指令的详细使用方法可以通过man 指令名来查看。
Snmplib:里面主要包含c语言方式的二次开发(代理或管理端开发)的动态库及静态库
Include:里面包含Snmplib库中开发所对应的头文件。(关于头文件中接口的使用可以参考http://www.net-snmp.org/docs/man/)中的介绍。
关于安装后的snmpd程序启动
将目录切到.snmpd的安装目录
cd /usr/local/sbin/
./snmpd [-Lo] [–f]
-Lo表示将打印输出到屏幕上默认不输出打印到屏幕,-f表示禁止将snmpd程序变为后台程序。
注意:这里可能会执行失败,原因应该是没有找到配置文件,当然你也可以通过如下命令来查看snmpd在运行时会搜索的配置文件的路径
snmpd -f -Lo -Dread_config
该指令会显示出snmpd在执行时会搜索哪些路径下的配置文件,一般默认在/usr/local/share/snmp路径下搜索
如果搜索路径下没有配置文件snmpd.conf,则需要通过命令动态生成配置文件
通过执行snmpconf -g basic_setup来一步一步的配置配置文件
最后配置文件进过压缩后的内容应该如下,否者也可能会出现指定失败
在这里插入图片描述
其中最后三行可以暂时不添加,后面会介绍,这里不会影响snmpd的运行。

5、net-snmp的代理端或管理端扩展的几种开发方式
5.1、关于扩展开发有下面几种方式
1,静态库的方式,该方式需要在net-snmp源码.安装前进行配置。暂不介绍
2,动态库开发,该方式在net-snmp源码安装后进行配置开发
3,子代理,该方式包括一个主代理与至少一个子代理,主代理与NMS(管理端)通讯,子代理与主代理通讯,子代理与主代理通讯,子代理实现了主代理没有实现的节点get.set等方法。这种方式要保证子代理之前的节点oid不要重复。
5.1、各种工具的使用方法
Net-snmp提供了很多的工具,供开发及调试使用,比如:
snmpd:代理端程序
Snmpget:
Snmpgetnext:
Snmpwalk:
Snmpbulkget:
Snmpbulkwalk:
Snmptable:
Snmpdelta:
Snmptrap:
snmpdf:
Snmptatus:
snmpnetstat:
snmptranslate:
snmpconf:配置工具,用于创建snmpd的配置文件
Net-snmp-config:用于查看net-snmp编译的时候使用了哪些编译选项,连接了那些库, 生成了哪些库,配置文件的路径等等。
Snmpusm:权限配置工具
Mib2c:根据mib文件内容生成相应的.c文件
等工具。
不同工具的使用通过下面命令格式
工具名 -h 可以查看该工具的使用方法
例如,net-snmp-config -h命令用来查看net-snmp安装的库及二进制程序的相关信息的SHELL脚本。及读取配置文件的路径的使用方法。
net-snmp-config --snmpconfpath 用来显示net-snmp命令读取配置文件的默认路径
6、代理端扩展开发的操作流程与方法

原因:为何需要扩展代理端,
在这里插入图片描述

如上图所示,net-snmp已经实现了MIB标准中的节点信息。可以通过 windows端工具mib-brower()进行查看如下图所示
在这里插入图片描述

比如,在企业的生产经营中,还需要通过net-snmp来查看服务器中某个服务进程中的某个交易数据的变化。这就需要机遇net-snmp进行扩展开发,以定制的方式为客户提供某些功能。这种方式成为扩展开发。
基于net-snmp开发有一套官方推荐的开发路程与方法,开发方法如下所示:
1,编写私有MIB文件;需要掌握MIB文件的编写规范
2,使用mib2c命令工具通过MIB文件来生成相关节点对应的模板代码
3,对2中的模板代理部分内容进行改写或实现填充。
4,编译私有模块:动态(采用动态开发方式),静态(采用静态开发方式),可执行程序(采用子代理开发方式)。
5,配置snmpd.conf和其他相关的配置文件
6,测试与调试

6.1、mib文件的编写
对于mib文件的编写,这里只做简单的介绍,详细的编写说明请参见《深入理解Net-Snmp》4.3节,下面为一个写好的mib文件TEST-MIB.mib的全部内容
–开始
TEST-MIB DEFINITIONS ::= BEGIN

–引入部分
IMPORTS
enterprises
FROM RFC1155-SMI
Integer32,OBJECT-TYPE
FROM SNMPv2-SMI
DisplayString
FROM SNMPv2-TC
TEXTUAL-CONVENTION
FROM SNMPv2-TC; --引用结束,用分号

–定义一个父节点,可以在下面定义所需要的所有的子节点
–enterprises的OID是1.3.6.1.4.1
test OBJECT IDENTIFIER ::= {enterprises 77587}

readobject  OBJECT-TYPE --对象名称
SYNTAX      Integer32   --类型
MAX-ACCESS read-only        --访问方式
STATUS      current     --状态
DESCRIPTION "test read" --描述
::= {test 1}                --父节点

writeObject OBJECT-TYPE --对象名称
SYNTAX      DisplayString   --类型
MAX-ACCESS read-write       --访问方式
STATUS      current     --状态
DESCRIPTION "test write"    --描述
::= {test 2}                --父节点

–结束定义
END

说明:
1,所有的MIB文件都是以“XXX DEFINITIONS ::= BEGIN”作为开头开头, 以“END”作为结尾的,其中两个连字符’–’表示注释符,同一行中它后面的内容不起作用,“XXX”为模块名。由用户自定义,不要与已经存在的模块名重复,建议模块名来表示该文件的文件名前缀。
2,IMPORTS是用来导入其他模块的。
3,对该文件的解读:该文件定义了一个mib模块,模块名为TEST-MIB,该模块定义了一个非叶子节点test ,挂在了enterprises (1.3.6.1.4.1)节点下面的77587号位,在test节点下面右定义了两个标量节点readobject,writeobject节点,并定义了这两个节点的一些其他的属性,一个可读,一个可读写。
将写好的mib文件放到/usr/local/share/snmp/mibs路径下,通过systemctl命令或者./snmpd来重启程序(这里要注意如果之前默认已经安装了snmpd,这里需要直接使用/usr/local/sbin/snmpd 命令来确保启动的是/usr/local/sbin/snmpd服务程序 ,否者会出现错误,否者使用ps -ef | grep snmpd 来查看snmpd的启动路径是否为/usr/local/sbin/)。通过指令snmptranslate来测试刚刚写的mib文件是否已经生效,如下图所示
在这里插入图片描述

如果出现上图说明已经成功生效
6.2、根据mib文件生成相应的c文件
通过mib2c命令可以直接生成相应的c文件
mib2c
备注:上面的C文件可以直接编写,想要直接编写建议先看懂上面的代码流程,才能直接编写。
mib2c -c mib2c.scalar.conf TEST::test
说明:使用mib2c.scalar.conf 表示为标量节点对象生成c文件,mib2c.iterate.conf 表示为表格节点生成c文件TEST::test表示mib文件中的模块名及节点名

,直接运行mib2c -c mib2c.scalar.conf TEST-MIB::test 会生成如下两个文件test.c ,.test.h
在这里插入图片描述

下面给出了tset.c及test.h中的全部内容,Test.h不需要改变,下面给出test.c修改签名的变化

修改前
test.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 “test.h”
//该函数将TEST::test中的两个节点对象readobject及writeobject的oid及对应的处理方法注册到snmpd中的mib对象数中
/** Initializes the test module */
void
init_test(void)
{
const oid readobject_oid[] = { 1,3,6,1,4,1,77587,1 };
const oid writeObject_oid[] = { 1,3,6,1,4,1,77587,2 };

DEBUGMSGTL((“test”, “Initializing\n”));

netsnmp_register_scalar(
    netsnmp_create_handler_registration("readobject", handle_readobject,
                           readobject_oid, OID_LENGTH(readobject_oid),
                           HANDLER_CAN_RONLY
    ));
netsnmp_register_scalar(
    netsnmp_create_handler_registration("writeObject", handle_writeObject,
                           writeObject_oid, OID_LENGTH(writeObject_oid),
                           HANDLER_CAN_RWRITE
    ));

}
//该函数用来实现readobject节点对象的处理方法
int
handle_readobject(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://表示响应snmpget
        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_readobject\n", reqinfo->mode );
        return SNMP_ERR_GENERR;
}

return SNMP_ERR_NOERROR;

}
int
handle_writeObject(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info requests)
{
int ret;
/
We are never called for a GETNEXT if it’s registered as a
“instance”, as it’s “magically” handled for us. */

/* a instance handler also only hands us one request at a time, so
   we don't need to loop over a list of requests; we'll only get one. */

switch(reqinfo->mode) {

    case MODE_GET://表示响应snmpget
        snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
                                 /* XXX: a pointer to the scalar's data */,
                                 /* XXX: the length of the data in bytes */);
        break;

    /*
     * SET REQUEST
     *
     * multiple states in the transaction.  See:
     * http://www.net-snmp.org/tutorial-5/toolkit/mib_module/set-actions.jpg
     */
    case MODE_SET_RESERVE1:
            /* or you could use netsnmp_check_vb_type_and_size instead */
        ret = netsnmp_check_vb_type(requests->requestvb, ASN_OCTET_STR);
        if ( ret != SNMP_ERR_NOERROR ) {
            netsnmp_set_request_error(reqinfo, requests, ret );
        }
        break;

    case MODE_SET_RESERVE2:
        /* XXX malloc "undo" storage buffer */
        if (/* XXX if malloc, or whatever, failed: */) {
            netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_RESOURCEUNAVAILABLE);
        }
        break;

    case MODE_SET_FREE:
        /* XXX: free resources allocated in RESERVE1 and/or
           RESERVE2.  Something failed somewhere, and the states
           below won't be called. */
        break;

    case MODE_SET_ACTION://表示响应snmpset
        /* XXX: perform the value change here */
        if (/* XXX: error? */) {
            netsnmp_set_request_error(reqinfo, requests, /* some error */);
        }
        break;

    case MODE_SET_COMMIT:
        /* XXX: delete temporary storage */
        if (/* XXX: error? */) {
            /* try _really_really_ hard to never get to this point */
            netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_COMMITFAILED);
        }
        break;

    case MODE_SET_UNDO:
        /* XXX: UNDO and return to previous value for the object */
        if (/* XXX: error? */) {
            /* try _really_really_ hard to never get to this point */
            netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_UNDOFAILED);
        }
        break;

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

return SNMP_ERR_NOERROR;

}
修改后
Test.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 “test.h”

/** Initializes the test module */
void
init_test(void)
{
const oid readobject_oid[] = { 1,3,6,1,4,1,77587,1 };
const oid writeObject_oid[] = { 1,3,6,1,4,1,77587,2 };

DEBUGMSGTL((“test”, “Initializing\n”));

netsnmp_register_scalar(
    netsnmp_create_handler_registration("readobject", handle_readobject,
                           readobject_oid, OID_LENGTH(readobject_oid),
                           HANDLER_CAN_RONLY
    ));
netsnmp_register_scalar(
    netsnmp_create_handler_registration("writeObject", handle_writeObject,
                           writeObject_oid, OID_LENGTH(writeObject_oid),
                           HANDLER_CAN_RWRITE
    ));

}

static long read_object_value = 123456;//自己添加
int
handle_readobject(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. */
read_object_value = 123456;
switch(reqinfo->mode) {

    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
                                 /* XXX: a pointer to the scalar's data */
                                 &read_object_value,
                                 /* XXX: the length of the data in bytes */
                                 sizeof(long));
        break;
    default:
        /* we should never get here, so this is a really bad error */
        snmp_log(LOG_ERR, "unknown mode (%d) in handle_readobject\n", reqinfo->mode );
        return SNMP_ERR_GENERR;
}

return SNMP_ERR_NOERROR;

}

static char write_object_value[1024]=“zhuchenglong”;//自己添加
int
handle_writeObject(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info requests)
{
int ret;
/
We are never called for a GETNEXT if it’s registered as a
“instance”, as it’s “magically” handled for us. */

/* a instance handler also only hands us one request at a time, so
   we don't need to loop over a list of requests; we'll only get one. */

switch(reqinfo->mode) {

    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
                                 /* XXX: a pointer to the scalar's data */
                                 write_object_value,
                                 /* XXX: the length of the data in bytes */
                                 strlen(write_object_value));
        break;

    /*
     * SET REQUEST
     *
     * multiple states in the transaction.  See:
     * http://www.net-snmp.org/tutorial-5/toolkit/mib_module/set-actions.jpg
     */
    case MODE_SET_RESERVE1:
            /* or you could use netsnmp_check_vb_type_and_size instead */
        ret = netsnmp_check_vb_type(requests->requestvb, ASN_OCTET_STR);
        if ( ret != SNMP_ERR_NOERROR ) {
            netsnmp_set_request_error(reqinfo, requests, ret );
        }
        break;

    case MODE_SET_RESERVE2:
        /* XXX malloc "undo" storage buffer */
        // if (/* XXX if malloc, or whatever, failed: */) {
        //     netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_RESOURCEUNAVAILABLE);
        // }
        break;

    case MODE_SET_FREE:
        /* XXX: free resources allocated in RESERVE1 and/or
           RESERVE2.  Something failed somewhere, and the states
           below won't be called. */
        break;

    case MODE_SET_ACTION:
        /* XXX: perform the value change here */
        // if (/* XXX: error? */) {
        //     netsnmp_set_request_error(reqinfo, requests, /* some error */);
        // }
        strcpy(write_object_value, "chenglongzhu");
        break;

    case MODE_SET_COMMIT:
        /* XXX: delete temporary storage */
        // if (/* XXX: error? */) {
        //     /* try _really_really_ hard to never get to this point */
        //     netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_COMMITFAILED);
        // }
        break;

    case MODE_SET_UNDO:
        /* XXX: UNDO and return to previous value for the object */
        // if (/* XXX: error? */) {
        //     /* try _really_really_ hard to never get to this point */
        //     netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_UNDOFAILED);
        // }
        break;

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

return SNMP_ERR_NOERROR;

}

通过上诉两个test.c文件的对比,开发人员与应该可以得知由mib2c生成后的文件中哪些内容需要自己修改。通过掌握这个test.c及test.h的代理流程及原理开发人员可以不用mib2c工具而自己直接编写TEST::MIB::test节点所需要的c文件。通过对test.c文件该改写后可以直接编译成可执行程序(采用子代理方式)或者动态库(采用动态库方式)或者静态库(采用静态库方式),下面只介绍子代理方式及动态库方式的开发及配置流程:
6.3、动态库开发流程及方法
原理描述:先通过gcc工具将test.c 编译成一个动态库libtest…so,在snmpd.conf配置文件中配置libtest…so的名字及存放路径,这样重启snmpd的时候 snmpd会先自动加载/usr/local/share/snmp/mibs目录下所有mib模块文件,然后根据mib模块中的节点名来加载对应节点的处理方法(对于TEST-MIB::test下的节点会通过libtest…so中的符号表中找到对应节点的初始化函数的实现void init_test(void)),然后将该节点的句柄挂在mib树上对应的节点上。
1、使用gcc -fPIC -shared test.c -o libtest.so 来生成libtest.so动态库
在这里插入图片描述

2、配置snmpd.conf文件中的libtest…so的名字及存放路径
在/etc/snmp/snmpd.conf中添加一行dlmod test /usr/local/shared/snmp/dlmod/libtest.so
在这里插入图片描述

Snmpd启动的时候会自动读取配置文件从/usr/local/shared/snmp/dlmod/路径下加载libtest.so动态库文件。在动态库libtest.so的符号表中搜索init_test函数。
通过在本地主机上直接执行如下指令如下结果说明
1,重启snmpd程序,可以杀死,再执行./snmpd
在这里插入图片描述

这里虽然在mib模块中writeobject节点配置了可读写,但是还会有权限访问的问题,估计需要在配置文件snmpd.conf上进行相应配置
6.4、子代理端的开发流程与方法
原理描述:子代理开发属于一个主代理与多个子代理关系,子代理数至少为一个,子代理实现了主代理里没有实现的节点方法,且多个子代理之间的节点oid不能重复。子代理与主代理是通过套接字通讯的(本地套接字/网络套接字)。主代理与子代理都是独立的可执行程序。需要先启动子主代理,此时主代理除了出开启161监听端口,还会开启一个705(可通过配置文件配置)端口来监听与子代理通讯,然后启动一个子代理,子代理会通过ip:705端口号与主代理建立连接,建立连接后子代理会主动向主代理发送一个注册请求,告诉主代理我这里由oid为.x.x.x.x.x.x.x0的节点的实现方法。主代理收到后会将该信息及与该子代理的通讯信息记录到自己的mib节点数上的对应的节点上,如果有管理端使用snmpget方法想要获取某个节点的信息。那么它会先将snmpget请求发给主代理.,主代理在收到该请求后会在本地的mib节点树上查找是否有该节点,如果有再判断该节点的实现方法是否在本地,还是在子代理那里,如果再子代理那里,则还需要向指定的子代理那里发送一个snmpget请求,子代理在收到来自主代理的snmpget请求后,会将响应发送主代理,主代理在收到响应后会将其发送给管理端。如下图所示为管理端,主代理,子代理之间的网络通讯图。
在这里插入图片描述

1、使用net-snmp-config命令将将修改后的test.c文件编译成可执行程序test
Net-snmp-config --complie-subagent --norm test test.c
[–norm]选项表示不会删除临时产生的中间件文件netsnmptmp.c
分析netsnmptmp.c中的函数发现里面是由main.c函数的。通过阅读及理解netsnmptmp.c的代理流程之后可以省去该步骤而自己编写netsnmptmp.c文件。或者直接使用gcc命令
gcc test.c netsnmptmp.15083.c -o test -lnetsnmp -lnetsnmpagent 也可编程成可执行程序test,这种方式方便将程序嵌入到其他程序中
2、配置snmd.conf文件如下图所示
在这里插入图片描述

3、测试结果如下图所示
…启动主代理
在这里插入图片描述

启动子代理
在这里插入图片描述

获取节点信息
在这里插入图片描述

7、管理端的扩展开发
管理端的c语言的方式开发需要用到libnetsnmp.so库及对应的头文件。
通过shell/python/perl方式则需要用到net-snmp的一些命令。
下面仅对snmptrapd及snmptrap指令进行介绍
7.1、snmptrapd的使用
snmptrapd介绍:
snmptrapd与snmpd一样是一个后台服务,启动后通过162端口不断地监听消息,可以通过配置snmptrapd.conf文件来控制snmptrapd服务在收到trap消息后的行为。详细配置请参见《深入理解-NET-SNMP》中7.2.3节,如下图给出了部分配置方式
在这里插入图片描述

用户自定义行为的配置如下图所示
在这里插入图片描述

命令snmptrapd -d -f –Lo 启动snmptrapd。
上面命令中的选项表示:
-C : 表示不使用net-snmp默认路径下的配置文件snmptrapd.conf;
-c : 指定snmptrapd.conf文件;
-d : 显示收到和发送的数据报,通过这个选项可以看到数据报文;
-f : 默认情况下,snmptrapd是在后台中运行的,加上这个选项,表示在前台运行;
-L : 指定日志记录在哪里,后面的o表示直接输出到屏幕上,如果是跟着f表示日志记录到指定的文件中;
snmptrapd -C -c /usr/local/share/snmp/snmptrapd.conf -df -Lf /tmp/log.txt的方式可以把接收的snmp报文输出到指定文件中
7.2、snmptrap的使用
The TYPE is a single character, one of:
i INTEGER
u UNSIGNED
c COUNTER32
s STRING
x HEX STRING
d DECIMAL STRING
n NULLOBJ
o OBJID
t TIMETICKS
a IPADDRESS
b BITS

SNMP V1 Examplpe
snmptrap -v1 -c public 10.10.12.219 1.3.6.1.4.1.1 10.10.12.219 2 3 1000 1.3.6.1.9.9.44.1.2.1 i 12 1.3.4.1.2.3.1 s test_snmptrap
指令各项参数的意思分别为:

snmptrap -v1 -c public 10.10.12.219 1.3.6.1.4.1.1 10.10.12.219 2 3 1000
命令 Snmp协议版本 共同体 Snmp管理端IP Enterprise-OID Snmp代理IP Trap类型 Trap特征码 uptime
1.3.6.1.9.9.44.1.2.1 I 1212 1.3.4.1.2.3.1 s test_snmptrap
被发送参数的OID 数据类型 数据值 被发送参数的OID 数据类型 数据值
SNMP V2c Examplpe
从上面可看到,发送V1版本的trap包有较多的参数,如uptime等,而在V2c版本中则交给了指令程序去做。
snmptrap -v 2c -c public 10.10.12.219 “aaa” 1.3.6.1.4.1.2345 SNMPv2-MIB::sysLocation.0 s “just here”
上面指令各项参数的意思分别为:

  • 10.10.12.219 “aaa”:分别是snmp管理端的IP和主机名称,主机名称可以为空;
  • 1.3.6.1.4.1.2345:企业OID,Enterprise-OID;
  • SNMPv2-MIB::sysLocation.0 s “just here”:分别是:数据OID、数据类型、数据值
  • 5
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于 net-snmp 的项目开发可以按照以下步骤进行: 1. 确定需求:明确项目的目标和功能要求,例如监控网络设备的状态信息、采集性能数据等。 2. 安装和配置 net-snmp:下载并安装 net-snmp 软件包,根据需要进行相应的配置,如设置 SNMP 代理、定义 MIB 文件等。 3. 编写代码:使用适合的编程语言(如 C、Python、Java)编写代码来与 SNMP 代理进行交互。net-snmp 提供了一系列的 API 接口,可以方便地实现 SNMP 操作,如获取设备信息、设置参数、发送 Trap 等。 4. 连接和通信:使用 SNMP 协议与网络设备建立连接,并通过 SNMP 消息进行通信。可以使用 SNMP 的 Get、Set、Walk 等操作来获取或修改设备的数据。 5. 数据处理和分析:对从设备获取到的数据进行处理和分析,根据需求进行相应的计算、统计或报表生成等操作。 6. 错误处理和异常处理:考虑到网络环境的复杂性,需要合理地处理错误和异常情况,如设备断连、超时等。 7. 测试和调试:编写测试用例来验证代码的正确性和功能完整性,并进行调试和优化。 8. 文档编写:编写项目文档,包括项目需求、设计、实现等内容,以方便后续的维护和扩展。 9. 部署和运行:将项目部署到目标环境中,并进行验证和运行。 需要注意的是,net-snmp 是一个功能强大的 SNMP 实现,提供了丰富的功能和接口,但同时也需要对 SNMP 协议有一定的了解。在开发过程中,可以参考 net-snmp 官方文档和示例代码,以及相关的 SNMP 标准。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值