Chinaunix首页 | 论坛 | 博客
  • 博客访问: 348113
  • 博文数量: 100
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 521
  • 用 户 组: 普通用户
  • 注册时间: 2014-10-31 11:37
个人简介

活到老,学到老

文章分类

全部博文(100)

文章存档

2018年(1)

2017年(2)

2016年(11)

2015年(82)

2014年(4)

我的朋友

分类: LINUX

2015-07-01 12:26:05

参考:http://blog.csdn.net/shanzhizi/article/details/11769491

用net-snmp扩展MIB库,实现方法可归结为四种:

1)一是静态库方式,通过修改配置头文件,在相应地方包含新引入的mib模块的.c和.h文件,然后重新编译库文件和扩展代码;这种方式不够灵活,每次修改扩展的MIB后,都需要重新编译snmpd和扩展的代码,再重新安装snmpd到系统中。

2)二是编译动态共享库,只需把新引入的MIB模块的.c和.h文件编译成动态库,通过设置能够让代理程序载入。

对于第二种方式,一需要编译成.so动态共享库,二需要原代理程序是否包含dlmod或load命令,三还要看系统是否支持。一般情况下仅支持Unix平台。

3)三是扩展一个子代理,让SNMPD以主代理的模式运行,对于SNMPD我们只要让它启动就可以,不需要任何的更改和配置,把子代理编译生成的程序运行起来就可以扩展自定义的MIB库。

4)用shell脚本来扩展

本文我们以第三种方法在linux上开发和测试

编写mib文件
mib文件的作用:
1、开发方便生成扩展程序的.c和.h
2、用户访问的时候,可以不用输oid,直接输节点名就可以访问。
注:编写mib文件可以用window下的一个软件方便编写,名字叫MG-SOFT MIB Browser
mib文件放在的目录在/usr/local/net-snmp/share/snmp/mibs下
自定义MIB库,如下:

  1. -- Test-MIB.my
  2. Test-MIB DEFINITIONS ::= BEGIN
  3. IMPORTS
  4. OBJECT-GROUP, MODULE-COMPLIANCE, NOTIFICATION-GROUP
  5. FROM SNMPv2-CONF
  6. enterprises, Integer32, Unsigned32, OBJECT-TYPE, MODULE-IDENTITY,
  7. NOTIFICATION-TYPE
  8. FROM SNMPv2-SMI
  9. DisplayString
  10. FROM SNMPv2-TC;
  11. -- October 09, 2002 at 14:50 GMT
  12. -- 1.3.6.1.4.1.16535
  13. Test MODULE-IDENTITY
  14. LAST-UPDATED "200210091450Z" -- October 09, 2002 at 14:50 GMT
  15. ORGANIZATION
  16. ""
  17. CONTACT-INFO
  18. ""
  19. DESCRIPTION
  20. "Video's Server MIB."
  21. ::= { enterprises 16535 }
  22. -- Node definitions
  23. -- This part will include all details about the Test.
  24. -- 1.3.6.1.4.1.16535.1
  25. Time OBJECT IDENTIFIER ::= { Test 1 }
  26. -- 1.3.6.1.4.1.16535.1.1
  27. GetTime OBJECT-TYPE
  28. SYNTAX DisplayString (SIZE (0..100))
  29. MAX-ACCESS read-only
  30. STATUS current
  31. DESCRIPTION
  32. "Example : 2013/4/11"
  33. ::= { Time 1 }
  34. END
  35. -- Test-MIB.my


  1. 每个oid必须是唯一的,1.3.6.1.4.1.16535.1.1,写完后我们测一个MIB库有没有问题,在linux机器上用snmptranslate -Tp -IR Test-MIB::Test显示结果如下:

  1. +--Test(16535)
  2. |
  3. +--Time(1)
  4. |
  5. +-- -R-- String GetTime(1)
  6. Textual Convention: DisplayString
  7. Size: 0..100
生成源
生成源码需要用到mib2c这个工具,需要先配置一下snmp.conf文件,在/usr/local/net-snmp/share/snmp/
snmp.conf

  1. mibdirs /usr/local/net-snmp/share/snmp/mibs
  2. mibs +ALL
记得改环境配置,否则在其他目录生成的话,不识别mib2c命令和用到的conf文件和文件。
我在~/.bashrc里的配置

mib2c可以根据mib库生成对应的源代码,有多种模板,这里我用固定的套路去生成
使用命令mib2c Test,先选2,后选1。1是生成string型,2是生成int型。
这是会发现在目录下多了一个.c和一个.h文件。
.h文件如下

  1. /*
  2.  * Note: this file originally auto-generated by mib2c using
  3.  * $
  4.  */
  5. #ifndef TEST_H
  6. #define TEST_H
  7.   
  8. /*
  9.  * function declarations
  10.  */
  11. void init_Test(void);
  12. Netsnmp_Node_Handler handle_GetTime;
  13.   
  14. #endif

.c文件

  1. /*
  2.  * Note: this file originally auto-generated by mib2c using
  3.  * $
  4.  */
  5.   
  6. #include <net-snmp/net-snmp-config.h>
  7. #include <net-snmp/net-snmp-includes.h>
  8. #include <net-snmp/agent/net-snmp-agent-includes.h>
  9. #include "Test.h"
  10.   
  11. /** Initializes the Test module */
  12. void
  13. init_Test(void)
  14. {
  15.     const oid GetTime_oid[] = { 1, 3, 6, 1, 4, 1, 16535, 1, 1 };
  16.   
  17.     DEBUGMSGTL(("Test", "Initializing\n"));
  18.   
  19.     netsnmp_register_scalar(netsnmp_create_handler_registration
  20.                             ("GetTime", handle_GetTime, GetTime_oid,
  21.                              OID_LENGTH(GetTime_oid), HANDLER_CAN_RONLY));
  22. }
  23.   
  24. int
  25. handle_GetTime(netsnmp_mib_handler *handler,
  26.                netsnmp_handler_registration *reginfo,
  27.                netsnmp_agent_request_info *reqinfo,
  28.                netsnmp_request_info *requests)
  29. {
  30.     /*
  31.      * We are never called for a GETNEXT if it's registered as a
  32.      * "instance", as it's "magically" handled for us.
  33.      */
  34.   
  35.     /*
  36.      * a instance handler also only hands us one request at a time, so
  37.      * we don't need to loop over a list of requests; we'll only get one.
  38.      */
  39.   
  40.     switch (reqinfo->mode) {
  41.   
  42.     case MODE_GET:
  43.         snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
  44.                                  /*
  45.                                   * XXX: a pointer to the scalar's data
  46.                                   */ ,
  47.                                  /*
  48.                                   * XXX: the length of the data in bytes
  49.                                   */ );
  50.         break;
  51.   
  52.   
  53.     default:
  54.         /*
  55.          * we should never get here, so this is a really bad error
  56.          */
  57.         snmp_log(LOG_ERR, "unknown mode (%d) in handle_GetTime\n",
  58.                  reqinfo->mode);
  59.         return SNMP_ERR_GENERR;
  60.     }
  61.   
  62.     return SNMP_ERR_NOERROR;
  63. }
修改.c文件如下

  1. /*
  2.  * Note: this file originally auto-generated by mib2c using
  3.  * $
  4.  */
  5.   
  6. #include <net-snmp/net-snmp-config.h>
  7. #include <net-snmp/net-snmp-includes.h>
  8. #include <net-snmp/agent/net-snmp-agent-includes.h>
  9. #include "Test.h"
  10. #include <time.h>
  11.   
  12. /** Initializes the Test module */
  13. void
  14. init_Test(void)
  15. {
  16.     const oid GetTime_oid[] = { 1, 3, 6, 1, 4, 1, 16535, 1, 1 };
  17.   
  18.     DEBUGMSGTL(("Test", "Initializing\n"));
  19.   
  20.     netsnmp_register_scalar(netsnmp_create_handler_registration
  21.                             ("GetTime", handle_GetTime, GetTime_oid,
  22.                              OID_LENGTH(GetTime_oid), HANDLER_CAN_RONLY));
  23. }
  24.   
  25. int
  26. handle_GetTime(netsnmp_mib_handler *handler,
  27.                netsnmp_handler_registration *reginfo,
  28.                netsnmp_agent_request_info *reqinfo,
  29.                netsnmp_request_info *requests)
  30. {
  31.     /*
  32.      * We are never called for a GETNEXT if it's registered as a
  33.      * "instance", as it's "magically" handled for us.
  34.      */
  35.      /*
  36.      * a instance handler also only hands us one request at a time, so
  37.      * we don't need to loop over a list of requests; we'll only get one.
  38.      */
  39.   
  40.     time_t t;
  41.     switch (reqinfo->mode) {
  42.     case MODE_GET:
  43.         time(&t);
  44.         char szTime[100];
  45.         snprintf(szTime,100,"%s",ctime(&t));
  46.         snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
  47.                                  /*
  48.                                   * XXX: a pointer to the scalar's data
  49.                                   */ szTime,
  50.                                  /*
  51.                                   * XXX: the length of the data in bytes
  52.                                   */ strlen(szTime));
  53.         break;
  54.   
  55.   
  56.     default:
  57.         /*
  58.          * we should never get here, so this is a really bad error
  59.          */
  60.         snmp_log(LOG_ERR, "unknown mode (%d) in handle_GetTime\n",
  61.                  reqinfo->mode);
  62.         return SNMP_ERR_GENERR;
  63.     }
  64.   
  65.     return SNMP_ERR_NOERROR;
  66. }
编译该.c文件,执行命令:net-snmp-config --compile-subagent Test Test.c,生成一个Test可执行文件。
其实,net-snmp-config程序生成了一个临时的C文件,netsnmptmp.12373.c 并与Test.c一起编译,生成了Test程序后又删除了该临时文件。在这里就不研究了。
我们先执行主代理(service snmpd start),再执行子代理./Test,再ps -ef | grep Test,看一下,可以看到Test程序自动在后台启动了。
执行命令:
snmpget -v2c -c public localhost 1.3.6.1.4.1.16535.1.1.0
snmpget -v2c -c public localhost Test-MIB:GetTime.0
可以获得该节点的值。
将.c文件加入项目中

点击(此处)折叠或打开

  1. /*
  2.  * Note: this file originally auto-generated by mib2c using
  3.  * $
  4.  */
  5.   
  6. #include <net-snmp/net-snmp-config.h>
  7. #include <net-snmp/net-snmp-includes.h>
  8. #include <net-snmp/agent/net-snmp-agent-includes.h>
  9. #include "Test.h"
  10. #include <time.h>
  11.   
  12. /** Initializes the Test module */
  13. void
  14. init_Test(void)
  15. {
  16.     const oid GetTime_oid[] = { 1, 3, 6, 1, 4, 1, 16535, 1, 1 };
  17.   
  18.     DEBUGMSGTL(("Test", "Initializing\n"));
  19.   
  20.     netsnmp_register_scalar(netsnmp_create_handler_registration
  21.                             ("GetTime", handle_GetTime, GetTime_oid,
  22.                              OID_LENGTH(GetTime_oid), HANDLER_CAN_RONLY));
  23. }
  24.   
  25. int
  26. handle_GetTime(netsnmp_mib_handler *handler,
  27.                netsnmp_handler_registration *reginfo,
  28.                netsnmp_agent_request_info *reqinfo,
  29.                netsnmp_request_info *requests)
  30. {
  31.     /*
  32.      * We are never called for a GETNEXT if it's registered as a
  33.      * "instance", as it's "magically" handled for us.
  34.      */
  35.     /*
  36.      * a instance handler also only hands us one request at a time, so
  37.      * we don't need to loop over a list of requests; we'll only get one.
  38.      */
  39.   
  40.     time_t t;
  41.     switch (reqinfo->mode) {
  42.     case MODE_GET:
  43.     time(&t);
  44.     char szTime[100];
  45.     snprintf(szTime,100,"%s",ctime(&t));
  46.         snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
  47.                                  /*
  48.                                   * XXX: a pointer to the scalar's data
  49.                                   */ szTime,
  50.                                  /*
  51.                                   * XXX: the length of the data in bytes
  52.                                   */ strlen(szTime));
  53.         break;
  54.   
  55.   
  56.     default:
  57.         /*
  58.          * we should never get here, so this is a really bad error
  59.          */
  60.         snmp_log(LOG_ERR, "unknown mode (%d) in handle_GetTime\n",
  61.                  reqinfo->mode);
  62.         return SNMP_ERR_GENERR;
  63.     }
  64.   
  65.     return SNMP_ERR_NOERROR;
  66. }
  67.   
  68. static int keep_running;
  69. RETSIGTYPE stop_server(int __attribute__((unused)) a) {
  70.         keep_running = 0;
  71. }
  72.   
  73. int main()
  74. {
  75.    const char *app_name = "Test";
  76.    /* we are a subagent */
  77.    netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1);
  78.   
  79.    /* initialize the agent library */
  80.    init_agent(app_name);
  81.   
  82.    /* initialize your mib code here */
  83.    init_Test(); //如果还需添加扩展,只需将生成.c中的init_*()函数添加到此就可以了。
  84.   
  85.    /* Test will be used to read Test.conf files. */
  86.    init_snmp(app_name);
  87.    keep_running = 1;
  88.    while(keep_running)
  89.    {
  90.         agent_check_and_process(1);/* block every 1 second */
  91.    }
  92.    /* at shutdown time */
  93.    snmp_shutdown(app_name);
  94.   
  95.    /* deinitialize your mib code here */
  96.   
  97.    /* shutdown the agent library */
  98.    shutdown_agent();
  99.    return 0;
  100. }
编译改函数使用gcc,编译,需要用到/usr/local/net-snmp/include里的头文件,和/usr/local/net-snmp/lib的库文件,libnetsnmp和libnetsnmpagent的动态的或者静态的库都行。使用动态库的话,记得在函数执行前修改ld.so.conf中添加动态库的路径,修改完以后记得ldconfig,更新一下。
执行生成的可执行文件,打印出“NET-SNMP version 5.7.2 AgentX subagent connected ”即为该程序执行成功。
可以调用snmpget去测试。
其他的扩展方式
1、动态库扩展
  编译命令:  net-snmp-config --compile-subagent Test.so Test.c -fPIC -shared
在snmpd.conf文件中添加    “dlmod Test /usr/local/net-snmp/share/snmp/mibs/Test.so”即可。
2、shell扩展:
在snmpd.conf文件中添加 “extend .1.3.6.1.4.1.16535.1.1 /bin/sh gettime.sh”



阅读(3096) | 评论(0) | 转发(0) |
0

上一篇:linux下snmp的安装

下一篇:linux下snmpset

给主人留下些什么吧!~~