net-snmp的MIBs扩展(linux下)

net-snmp的MIBs扩展

  • net-snmp的MIBs扩展

    • 1 编译安装net-snmp
    • 2 编写MIB文件
      • MIB文件描述
      • 一个简单的示例
    • 3 使自定义的MIB文件生效
    • 4 实现agent代理程序
      • 使用mib2c程序来生成.c和.h文件。
      • 只读节点readObject.c和readObject.h的修改。
        • 编译一下
        • 运行测试一下
      • 读写节点writeObject.c的修改
        • 编译运行测试一下
  • MIB的相关概念
    在SNMP网络管理中,管理信息库MIB(Management Information Base)是对于通过网络管理协议可以访问的信息。这些信息更具体的理解为网管中被管资源,而网络管理中的资源是以对象来表示,每一个对象表示被管资源某一方面的属性,这些对象的集合形成管理信息库。
  • 先说一下系统环境
[email protected]:~$ uname -a
Linux o-pc 3.19.0-21-generic #21-Ubuntu SMP Sun Jun 14 18:31:11 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

1 编译安装net-snmp

具体的就不说了,见此处:

net-snmp-5.7.3配置编译安装http://www.cnblogs.com
/oloroso/p/4595123.html

2 编写MIB文件

MIB文件描述

MIB文件是用

ASN.1

语法来描述的,所以为了精确定义MIB中各管理对象,用户不得不参考一些ASN.1语法的有关文档如RFC1155、RFC1212等等来定义设备自己的MIB。ASN.1是抽象句法表示法一

(Abstract Syntax Notation One)

的简称,对于每个管理对象它都用文本来描述,一般文件的后缀名都用“.mib”。

关于MIB文件示例,可以见编译安装后的net-snmp目录,一般是

/usr/local/net-snmp/share/snmp/mibs/

ls /usr/local/net-snmp/share/snmp/mibs/
AGENTX-MIB.txt                       IPV6-TCP-MIB.txt                     SNMP-NOTIFICATION-MIB.txt
...
IPV6-MIB.txt                         SNMP-MPD-MIB.txt                     UDP-MIB.txt

一个简单的示例

这里我们写一个MIB文件,含有两个节点,一个是只读权限的,一个是读写权限的。然后把这个文件命名为 myTest.mib 然后保存到 /usr/local/net-snmp/share/snmp/mibs/ 目录。

--开始
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
 test OBJECT IDENTIFIER ::= {enterprises 77587}

readObject  OBJECT IDENTIFIER ::= {test 1}
writeObject OBJECT IDENTIFIER ::= {test 2}  

    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

3 使自定义的MIB文件生效

要使得这个自定义的MIB生效,最简单的办法就是把它的内容添加到已有的某个MIB文件中就是了。比如 cat myTest.mib >> 原有MIB文件 ,然后重启一下 snmpd 服务就是了。不过这是一种投机的做法。
正常一点的做法是:

  • 将自定义的MIB文件的开始处定义的名称加入到环境变量

    MIBS

    中,譬如这里

    TEST-MIB DEFINITIONS ::= BEGIN

    中的

    TEST-MIB

    还可以添加到

    snmpd

    的配置文件中。因为本机上是采取的添加到

    bash

    的环境变量中的,所以在

    ~/.bashrc

    文件中添加了一行


    export MIBS=+TEST-MIB

  • 杀死

    snmpd

    进程,然后重启它。
  • 使用

    snmptranslate

    查看自定义的

    TEST-MIB

    是否被加载了。
[email protected]:~/snmp/mibs$ /usr/local/net-snmp/bin/snmptranslate -Tp -IR test
+--test(77587)
   |
   +-- -R-- Integer32 readObject(1)
   +-- -RW- String    writeObject(2)
            Textual Convention: DisplayString
            Size: 0..255

4 实现agent代理程序

我们可以先来获取一下前面定义的 readObject 节点的值试试。
因为

enterprises

的OID是

1.3.6.1.4

,而

test



enterprises

的叶子(77585),而

readObject

又是

test

的叶子节点(1)。所以其OID为

1.3.6.1.4.77585.1

下面使用snmpget来测试一下

[email protected]:~/snmp/mibs$ /usr/local/net-snmp/bin/snmpget -c public -v 2c localhost 1.3.6.1.4.1.77587.1
TEST-MIB::readObject = No Such Object available on this agent at this OID

结果是No Such Object available on this agent at this OID,即

使用mib2c程序来生成 .c .h 文件。

使用以下命令来生成,两条命令的 -c 后跟的配置文件是不同的,因为两个节点的类型不一样。第一个是数字(integer32,counter,time)的配置,第二个是其它类型的。

mib2c -c mib2c.int_watch.conf readObject
mib2c -c mib2c.scalar.conf writeObject

只读节点readObject.c和readObject.h的修改。

readObject.h文件就不改了,这里没什么必要。
先来看一下readObject.c文件。(这里我把不重要的删掉了)

所做的修改就是在

init_readObject

函数中添加了一句

readObject = 12345;

。这个是随性而为的。我们只需要知道,当使用

snmpget

来获取

readObject

节点值的时候,获取的就是这个变量的值。

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

//这一句是mib2c生成的,默认值设为0
long    readObject = 0;  /* XXX: set default value */

void
init_readObject(void)
{
  netsnmp_handler_registration *reg;

    const oid readObject_oid[] = { 1,3,6,1,4,1,77587,1 };
  static netsnmp_watcher_info readObject_winfo;

  DEBUGMSGTL(("readObject", "Initializing the readObject module\n"));

/******************************************************/
    //这里是我修改的,以便于验证其有效
    readObject = 12345;

/******************************************************/
    DEBUGMSGTL(("readObject",
                "Initializing readObject scalar integer.  Default value = %ld\n",
                readObject));
    reg = netsnmp_create_handler_registration(
             "readObject", NULL,
              readObject_oid, OID_LENGTH(readObject_oid),
              HANDLER_CAN_RONLY);
    netsnmp_init_watcher_info(&readObject_winfo, &readObject, sizeof(long),
                  ASN_INTEGER, WATCHER_FIXED_SIZE);
if (netsnmp_register_watched_scalar( reg, &readObject_winfo ) < 0 ) {
        snmp_log( LOG_ERR, "Failed to register watched readObject" );
    }

  DEBUGMSGTL(("readObject",
              "Done initalizing readObject module\n"));
}

编译一下

编译的时候需要使用到另一个工具 net-snmp-config 。这个工具用来做两件事,一个是生成中间代码,然后使用gcc来编译它。
为什么要生成中间代码呢?你看上面的生存的

readObject.c

中没有main函数就知道了吧。

具体使用如下

net-snmp-config --compile-subagent readObject readObject.c
  • –compile-subagent的意思是编译为subagent程序。
  • readObject是编译后输出程序名
  • readObject.c是要编译的文件

还可以加上 --norm 参数来阻止编译后删除生成的中间代码文件。我们可以试一下。

[email protected]:~/snmp/mibs$ net-snmp-config --compile-subagent --norm readObject readObject.c
generating the tmporary code file: netsnmptmp.25506.c
void init_readObject(void);
checking for init_readObject in readObject.c
init_readObject(void)
checking for shutdown_readObject in readObject.c
running: gcc  -fno-strict-aliasing -g -O2 -Ulinux -Dlinux=linux  -D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fwrapv -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64  -I/usr/lib/x86_64-linux-gnu/perl/5.20/CORE   -I. -I/usr/local/net-snmp/include -o readObject netsnmptmp.25506.c  readObject.c  -L/usr/local/net-snmp/lib -lnetsnmpmibs -lnetsnmpagent -lnetsnmp -lnetsnmpmibs -ldl  -lnetsnmpagent  -Wl,-E -lnetsnmp
leaving the tmporary code file: netsnmptmp.25506.c
subagent program readObject created

编译后我们可以看到,当前目录下出现了编译后的程序 readObject 和一个 netsnmptmp.25506.c 的文件。你把它打开,就可以看到这是一个具有 main 函数的.c源文件了。简化之后的代码如下了。

#include "readObject.h"
const char *app_name = "readObject";
static int reconfig = 0;

extern int netsnmp_running;

int
main (int argc, char **argv)
{
    ...
  while ((arg = getopt(argc, argv, ...)) != EOF) {
    ...
  }
    ...

  /* 初始化agent库 *
  /*initialize the agent library */
  init_agent(app_name);

  /* i初始化你的mib代码 */
  /* initialize your mib code here */
  init_readObject();

  /* readObject will be used to read readObject.conf files. */
  /* readObject will be used to read readObject.conf files. */
  init_snmp("readObject");
  ...
  exit(0);
}

运行测试一下

这里我们先启动这个 readObject 的程序,然后再去重新 snmpget 获取节点 readObeject 的值。
注意,这个

readObject

默认是守护进程。

获取结果如下,可以看到成功获取了。

[email protected]:~/snmp/mibs$ /usr/local/net-snmp/bin/snmpget -c public -v 2c localhost 1.3.6.1.4.1.77587.1
...

TEST-MIB::readObject.0 = INTEGER: 12345

读写节点writeObject.c的修改

下面是修改后的writeObject.c文件

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

//这里是添加的,buf用于保存控制端设置的值,也用于返回。
#define BUFSIZE 1024
static char buf[BUFSIZE] = "test Write";    //给一个默认值

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

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

    netsnmp_register_scalar(
        netsnmp_create_handler_registration("writeObject", handle_writeObject,
                               writeObject_oid, OID_LENGTH(writeObject_oid),
                               HANDLER_CAN_RWRITE
        ));
}

int
handle_writeObject(netsnmp_mib_handler *handler,
                          netsnmp_handler_registration *reginfo,
                          netsnmp_agent_request_info   *reqinfo,
                          netsnmp_request_info         *requests)
{
    int ret;

    switch(reqinfo->mode) {
    //是获取操作
        case MODE_GET:
            snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
             /*这里填buf,用于返回数据给控制端*/      buf  /* XXX: a pointer to the scalar‘s data */,
             /*这里是buf数据字节数,注意writeObject类型*/ strlen(buf)  /* 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
         */
    //下面是设置操作的,也就是snmpset

        case MODE_SET_RESERVE1: //这个不管它
                /* or you could use netsnmp_check_vb_type_and_size instead */
            ret = netsnmp_check_vb_type(requests->requestvb, ASN_OCTET_STR);
            if ( ret != SNMP_ERR_NOERROR ) {
                netsnmp_set_request_error(reqinfo, requests, ret );
            }
            break;

        case MODE_SET_RESERVE2: //这个也不管它
            /* XXX malloc "undo" storage buffer */
            //我们不需要动态申请内存,直接略过
            if ( 0 /* XXX if malloc, or whatever, failed: */) {
                netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_RESOURCEUNAVAILABLE);
            }
            break;

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

    /****************************************************************/
    //  这里是我们的重点,控制端传过来的数据就在这里获取

        case MODE_SET_ACTION:
            /* XXX: perform the value change here */
            /* 获取控制端使用snmpset传来的数据 */
            memcpy(buf,requests->requestvb->buf,requests->requestvb->val_len);

            if (0/* XXX: error? */) {   //这个先不管了
                netsnmp_set_request_error(reqinfo, requests, 0 /* some error */);
            }
            break;
//下面的都不管了
        case MODE_SET_COMMIT:
            /* XXX: delete temporary storage */
            if (0 /* XXX: error? */) {
                /* try _really_really_ hard to never get to this point */
                netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_COMMITFAILED);
            }
            break;

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

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

    return SNMP_ERR_NOERROR;
}

编译运行测试一下

编译还是和前面说的一样,就不详细说了。
一样运行后进行获取一次试试。这里使用的snmpbulkget而不散snmpget。是因为任性而已。

[email protected]:~/snmp/mibs$  snmpbulkget -c public -v 2c localhost writeObject.0
MY-TEST-MIB::writeObject.0 = STRING: test Write
[email protected]:~/snmp/mibs$ snmpget -c public -v 2c localhost writeObject.0
MY-TEST-MIB::writeObject.0 = STRING: test Write

可以看大获取是没有问题的,那么设置一下试试。设置要使用到 snmpset 工具,使用方式和 snmpget 类似。只是需要在最后加上要设置的数据的类型和数据。

snmpset -c public -v 2c localhost writeObject.0 s "nihao"

数据类型参数可以使用 snmpset --help 来查看,其结果如下

  TYPE: one of i, u, t, a, o, s, x, d, b
    i: INTEGER, u: unsigned INTEGER, t: TIMETICKS, a: IPADDRESS
    o: OBJID, s: STRING, x: HEX STRING, d: DECIMAL STRING, b: BITS
    U: unsigned int64, I: signed int64, F: float, D: double

设置完成之后再次获取试试。

[email protected]:~/snmp/mibs$ snmpget -c public -v 2c localhost writeObject.0
MY-TEST-MIB::writeObject.0 = STRING: nihao

如果测试的时候碰到设置不成功的情况,检查一下snmpd的配置文件(通常是snmpd.conf)中权限设置的问题。

[email protected]:~/snmp/mibs$ snmpset -c public -v 2c localhost writeObject.0 s "nihao"
Error in packet.
Reason: noAccess
Failed object: MY-TEST-MIB::writeObject.0
时间: 2024-10-09 13:48:29

net-snmp的MIBs扩展(linux下)的相关文章

Snmp学习总结(六)——linux下安装和配置SNMP

一.安装SNMP 1.1.下载Net-SNMP的源代码 选择一个SNMP版本,比如5.7.1,下载地址如下:http://sourceforge.net/projects/net-snmp/files/net-snmp/5.7.1/,如下图所示: 下载完成之后得到如下图所示的一个压缩包 1.2.把压缩包传输到远程的Linux服务器 把压缩包使用FTP传输工具传输到远程的Linux服务器 上传成功后在linux的root目录下就可以看到压缩包了,如下图所示: 也可以在linux命令行窗口使用ls命

linux下安装php扩展redis缓存

下载phpredis安装包 wget https://github.com/nicolasff/phpredis/tarball/master 在下载目录解压phpredis.tar.gz tar zxvf phpredis.tar.gz cd phpredis 使用php的phpize编译安装包(需要进入到解压出来的目录里面) /usr/local/php/bin/phpize 设置配置 ./configure --with-php-config=/usr/local/php/bin/php-

linux下增加pdo-mysql扩展

默认的PHP安装,只安装了常用默认模块,一些不常用或少用的,就没有默认安上 可通过如下方法增加,如下以增加pdo-mysql为例 wget http://pecl.php.net/get/PDO_MYSQL-1.0.2.tgztar zxvf PDO_MYSQL-1.0.2.tgzcd PDO_MYSQL-1.0.2/www/wdlinux/php/bin/phpize./configure --with-php-config=/www/wdlinux/php/bin/php-config --

VMware 下扩展linux硬盘空间

linux下扩展硬盘有很多种方式,在扩展之前,尽量看看自己的空间存在的有哪些盘,然后再进行扩展.如果是扩展的话,磁盘的符号和已经有的符号一样,比如都是sda的设备,知识分区不同,可能是sda3 sda4 如果是添加的话,相对于一个新的硬盘,可能是sdb  sdc 很多人在学习Nutch.Hadoop或者熟悉Linux操作系统时都会选择在VMWare上安装Linux虚拟机,而又往往不想分配给Linux虚拟机足够大的硬盘空间,这就容易导致使用Linux一段时间后,发现虚拟机上的硬盘空间不够了,此时怎

Linux下PHP安装配置MongoDB数据库连接扩展

说明: 操作系统:CentOS 5.X 64位 MongoDB数据库服务器: IP地址:192.168.21.130 Web服务器: IP地址:192.168.21.127 PHP安装路径:/usr/local/php 实现目的: 安装PHP的MongoDB数据库扩展,通过PHP程序连接MongoDB数据库 具体操作: 一.安装PHP的MongoDB数据库扩展(在Web服务器192.168.21.127上操作) 下载地址:http://pecl.php.net/get/mongo-1.5.1.t

linux下安装opcache扩展

linux下安装opcache扩展 参考:http://www.php.net/manual/zh/opcache.installation.php 1 2 3 4 5 6 7 wget http://pecl.php.net/get/zendopcache-7.0.2.tgz tar zxvf zendopcache-7.0.2.tgz cd zendopcache-7.0.2 /usr/local/php/bin/phpize ./configure --with-php-config=/u

PHP扩展类ZipArchive实现压缩解压Zip文件和文件打包下载 &amp;&amp; Linux下的ZipArchive配置开启压缩

PHP ZipArchive 是PHP自带的扩展类,可以轻松实现ZIP文件的压缩和解压,使用前首先要确保PHP ZIP 扩展已经开启,具体开启方法就不说了,不同的平台开启PHP扩增的方法网上都有,如有疑问欢迎交流.这里整理一下常用的示例供参考. 一.解压缩zip文件 ? 1 2 3 4 5 6 7 8 9 10 11 $zip = new ZipArchive;//新建一个ZipArchive的对象 /* 通过ZipArchive的对象处理zip文件 $zip->open这个方法的参数表示处理的

Linux下PHP安装oci8扩展

PHP通常搭配Mysql使用,但有时候也会连接到Oracle数据库.安装PHP的oci8扩张之前,需要先安装Oracle Instant Client( basic 或 basic lite 版就行了).因为我们是从源码安装PHP扩展,所以还需要下载 Instant Client SDK.Oracle Instant Client相关软件包的下载请进入以下链接:http://www.oracle.com/technetwork/database/features/instant-client/i

LINUX下用PHPIZE安装PHP GD扩展

环境:LNMP in centOS 6.4. linux下PHP的扩展可以用phpize的方法,比较简单地进行启用. 以下以PHP-GD2 库安装为例子. sudo yum install php-gd2 png jpeg freetype //YUM安装扩展 cd /app/php-5.4.13/ext/gd //这里的php-5.4.13/文件夹是我当初解压PHP安装包得到的. phpize ./configure --with-png-dir --with-freetype-dir --w