windows下使用net-snmp实现agent扩展(二)

刚刚实现了int型的get命令,可能更多的情况下,我们更需要的是字符串类型的。在实现int型的时候,用到了netsnmp_register_int_instance这个函数,很自然想到如果是string型的,用类似的netsnmp_register_string_instance,或者netsnmp_register_char_instance不就行了?很可惜的是:net-snmp并没有提供这两个函数。通过查找,在net-snmp5.7.1/agent/mibgroup/examples下面,有个watched.c文件,这里提供了对字符串类型的操作。实际上,net-snmp将string型归到了scalar类型里,做了统一的处理。好,看代码:

watched.h文件:

  1. #ifndef EXAMPLES_WATCHED_H   
  2. #define EXAMPLES_WATCHED_H  
  3. #ifdef __cplusplus   
  4. extern "C" {   
  5. #endif  
  6. void init_watched(void);  
  7. #ifdef __cplusplus   
  8. }   
  9. #endif  
  10. #endif /* EXAMPLES_WATCHED_H */  
#ifndef EXAMPLES_WATCHED_H 
#define EXAMPLES_WATCHED_H
#ifdef __cplusplus 
extern "C" { 
#endif
void init_watched(void);
#ifdef __cplusplus 
} 
#endif
#endif /* EXAMPLES_WATCHED_H */

watched.c文件:

  1. /* 
  2.  * start by including the appropriate header files 
  3.  */  
  4. #include <net-snmp/net-snmp-config.h>  
  5. #include <net-snmp/net-snmp-includes.h>  
  6. #include <net-snmp/agent/net-snmp-agent-includes.h>  
  7.   
  8. void init_watched_string(void);  
  9.   
  10. void init_watched(void)  
  11. {  
  12.     init_watched_string();  
  13. }  
  14.   
  15. void init_watched_string(void)  
  16. {  
  17.     /* 
  18.      * the storage for our string. It must be static or allocated. 
  19.      * we use static here for simplicity. 
  20.      */  
  21.     static char my_string[256] = "welcome to vcsky.net!";  
  22.   
  23.     /* 
  24.      * the OID we want to register our string at.  This should be a 
  25.      * fully qualified instance.  In our case, it's a scalar at: 
  26.      * NET-SNMP-EXAMPLES-MIB::netSnmpExampleString.0  (note the trailing 
  27.      *  0 which is required for any instantiation of any scalar object) 
  28.      */  
  29.     oid             my_registration_oid[] =  
  30.         { 1, 3, 6, 1, 4, 1, 8072, 2, 1, 3, 0 };  
  31.   
  32.     /* 
  33.      * variables needed for registration 
  34.      */  
  35.     netsnmp_handler_registration *reginfo;  
  36.     static netsnmp_watcher_info watcher_info;  
  37.     int watcher_flags;  
  38.   
  39.     /* 
  40.      * a debugging statement.  Run the agent with -Dexample_string_instance 
  41.      * to see the output of this debugging statement. 
  42.      */  
  43.     DEBUGMSGTL(("example_string_instance",  
  44.                 "Initalizing example string instance.  Default value = %s\n",  
  45.                 my_string));  
  46.   
  47.     /* 
  48.      * If we wanted a callback when the value was retrieved or set 
  49.      * (even though the details of doing this are handled for you), 
  50.      * you could change the NULL pointer below to a valid handler 
  51.      * function. 
  52.      * 
  53.      * Change RWRITE to RONLY for a read-only string. 
  54.      */  
  55.     reginfo = netsnmp_create_handler_registration("my example string", NULL,  
  56.                                                   my_registration_oid,  
  57.                                                   OID_LENGTH(my_registration_oid),  
  58.                                                   HANDLER_CAN_RWRITE);  
  59.   
  60.     /* 
  61.      * the three options for a string watcher are: 
  62.      *   fixed size string (length never changes) 
  63.      *   variable size (length can be 0 - MAX, for some MAX) 
  64.      *   c string (length can be 0 - MAX-1 for some max, \0 is not a valid 
  65.      *     character in the string, the length is provided by strlen) 
  66.      * 
  67.      * we'll use a variable length string. 
  68.      */  
  69.      watcher_flags =WATCHER_MAX_SIZE;  
  70.     /* 
  71.      * create the watcher info for our string. 
  72.      */  
  73.     netsnmp_init_watcher_info6(&watcher_info, my_string, strlen(my_string),  
  74.                                ASN_OCTET_STR, watcher_flags,  
  75.                                sizeof(my_string), NULL);  
  76.   
  77.     /* 
  78.      * the line below registers our "my_string" variable above as 
  79.      * accessible and makes it writable. 
  80.      */  
  81.     netsnmp_register_watched_instance(reginfo, &watcher_info);  
  82.   
  83.     DEBUGMSGTL(("example_string_instance",  
  84.                 "Done initalizing example string instance\n"));  
  85. }  
/*
 * start by including the appropriate header files
 */
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>

void init_watched_string(void);

void init_watched(void)
{
    init_watched_string();
}

void init_watched_string(void)
{
    /*
     * the storage for our string. It must be static or allocated.
     * we use static here for simplicity.
     */
    static char my_string[256] = "welcome to vcsky.net!";

    /*
     * the OID we want to register our string at.  This should be a
     * fully qualified instance.  In our case, it's a scalar at:
     * NET-SNMP-EXAMPLES-MIB::netSnmpExampleString.0  (note the trailing
     *  0 which is required for any instantiation of any scalar object)
     */
    oid             my_registration_oid[] =
        { 1, 3, 6, 1, 4, 1, 8072, 2, 1, 3, 0 };

    /*
     * variables needed for registration
     */
    netsnmp_handler_registration *reginfo;
    static netsnmp_watcher_info watcher_info;
    int watcher_flags;

    /*
     * a debugging statement.  Run the agent with -Dexample_string_instance
     * to see the output of this debugging statement.
     */
    DEBUGMSGTL(("example_string_instance",
                "Initalizing example string instance.  Default value = %s\n",
                my_string));

    /*
     * If we wanted a callback when the value was retrieved or set
     * (even though the details of doing this are handled for you),
     * you could change the NULL pointer below to a valid handler
     * function.
     *
     * Change RWRITE to RONLY for a read-only string.
     */
    reginfo = netsnmp_create_handler_registration("my example string", NULL,
                                                  my_registration_oid,
                                                  OID_LENGTH(my_registration_oid),
                                                  HANDLER_CAN_RWRITE);

    /*
     * the three options for a string watcher are:
     *   fixed size string (length never changes)
     *   variable size (length can be 0 - MAX, for some MAX)
     *   c string (length can be 0 - MAX-1 for some max, \0 is not a valid
     *     character in the string, the length is provided by strlen)
     *
     * we'll use a variable length string.
     */
     watcher_flags =WATCHER_MAX_SIZE;
    /*
     * create the watcher info for our string.
     */
    netsnmp_init_watcher_info6(&watcher_info, my_string, strlen(my_string),
                               ASN_OCTET_STR, watcher_flags,
                               sizeof(my_string), NULL);

    /*
     * the line below registers our "my_string" variable above as
     * accessible and makes it writable.
     */
    netsnmp_register_watched_instance(reginfo, &watcher_info);

    DEBUGMSGTL(("example_string_instance",
                "Done initalizing example string instance\n"));
}

 编译运行(注意在入口函数中将init_nstAgentSubagentObject替换为init_watched)。

打开cmd,测试一下:snmpget -v1 -c public localhost 1.3.6.1.4.1.8072.2.1.3.0
返回结果:NET-SNMP-MIB::netSnmp.2.1.3.0 = STRING: "welcome to vcsky.net!" snmpset -v1 -c public localhost 1.3.6.1.4.1.8072.2.1.3.0 s "havenzhao”

返回结果:NET-SNMP-MIB::netSnmp.2.1.3.0 = STRING: "havenzhao" OK,没问题! 接下来,我们想改变my_string这个变量的值,这个值需要从程序的其它地方获得,这样才能起到监测的作用。先简单改变一下试试看,能否正确运行: 修改下watched.c文件,添加一行为my_string改变值的语句,标红的代码即是。

  1. #include <net-snmp/net-snmp-config.h>  
  2. #include <net-snmp/net-snmp-includes.h>  
  3. #include <net-snmp/agent/net-snmp-agent-includes.h>  
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
static char my_string[256] = "welcome to vcsky.net!"; //作为全局变量

/*模拟在其它代码中改变要监测的my_string值的函数,此函数可以放在定时器中,或者其它能够动态改变my_string值的代码段里,以保证获取的my_string值是变化的。别忘了在头文件watched.h里声明*/ 

  1. void change_string_value()  
  2. {  
  3.     strcpy(my_string, "haven zhao");  
  4. }  
  5.   
  6. void init_watched_string(void);  
  7.   
  8. void init_watched(void)  
  9. {  
  10.     init_watched_string();  
  11. }  
  12.   
  13. void init_watched_string(void)  
  14. {  
  15.     oid             my_registration_oid[] =  
  16.         { 1, 3, 6, 1, 4, 1, 8072, 2, 1, 3, 0 };  
  17.   
  18.     netsnmp_handler_registration *reginfo;  
  19.     static netsnmp_watcher_info watcher_info;  
  20.     int watcher_flags;  
  21.   
  22.     DEBUGMSGTL(("example_string_instance",  
  23.                 "Initalizing example string instance.  Default value = %s\n",  
  24.                 my_string));  
  25.   
  26.     reginfo = netsnmp_create_handler_registration("my example string", NULL,  
  27.                                                   my_registration_oid,  
  28.                                                   OID_LENGTH(my_registration_oid),  
  29.                                                   HANDLER_CAN_RWRITE);  
  30.   
  31. watcher_flags = WATCHER_MAX_SIZE;  
  32.   
  33. netsnmp_init_watcher_info6(&watcher_info, my_string, strlen(my_string),  
  34. ASN_OCTET_STR, watcher_flags,  
  35. sizeof(my_string), NULL);  
  36.   
  37. netsnmp_register_watched_instance(reginfo, &watcher_info);  
  38.   
  39. DEBUGMSGTL((“example_string_instance”,  
  40. “Done initalizing example string instance\n”));  
  41. }  
void change_string_value()
{
    strcpy(my_string, "haven zhao");
}

void init_watched_string(void);

void init_watched(void)
{
    init_watched_string();
}

void init_watched_string(void)
{
    oid             my_registration_oid[] =
        { 1, 3, 6, 1, 4, 1, 8072, 2, 1, 3, 0 };

    netsnmp_handler_registration *reginfo;
    static netsnmp_watcher_info watcher_info;
    int watcher_flags;

    DEBUGMSGTL(("example_string_instance",
                "Initalizing example string instance.  Default value = %s\n",
                my_string));

    reginfo = netsnmp_create_handler_registration("my example string", NULL,
                                                  my_registration_oid,
                                                  OID_LENGTH(my_registration_oid),
                                                  HANDLER_CAN_RWRITE);

watcher_flags = WATCHER_MAX_SIZE;

netsnmp_init_watcher_info6(&watcher_info, my_string, strlen(my_string),
ASN_OCTET_STR, watcher_flags,
sizeof(my_string), NULL);

netsnmp_register_watched_instance(reginfo, &watcher_info);

DEBUGMSGTL((“example_string_instance”,
“Done initalizing example string instance\n”));
}

 为了方便,我们把change_string_value()函数放在入口函数文件(example-demon.c)的死循环里: while(keep_running) { 

    /* if you use select(), see snmp_select_info() in snmp_api(3) */ 
    /*           --- OR ---        */ 
     change_string_value(); //放在这里了 
    agent_check_and_process(1); /* 0 == don't block */ 
}

再次编译运行,看看有没有达到效果: 
输入:snmpget -v1 -c public localhost 1.3.6.1.4.1.8072.2.1.3.0 
返回:NET-SNMP-MIB::netSnmp.2.1.3.0 = Hex-STRING: 68 61 76 65 6E 20 7A 68 61 6F 00 76 
出现乱码,没有成功!

再试试set命令:snmpset -v1 -c public localhost 1.3.6.1.4.1.8072.2.1.3.0 s "haven" 
返回:NET-SNMP-MIB::netSnmp.2.1.3.0 = STRING: "haven" 
可见set成功!try again,再输入get命令:snmpget -v1 -c public localhost 1.3.6.1.4.1.8072.2.1.3.0 
返回:NET-SNMP-MIB::netSnmp.2.1.3.0 = STRING: "haven" 
这次却成功了。

难道要先set,再get,才行?什么情况?再试一次! 
输入:snmpset -v1 -c public localhost 1.3.6.1.4.1.8072.2.1.3.0 s "vcsky.NET haven zhao" 
返回:NET-SNMP-MIB::netSnmp.2.1.3.0 = STRING: "vcsky.net haven zhao" 
输入:snmpget -v1 -c public localhost 1.3.6.1.4.1.8072.2.1.3.0 
返回:NET-SNMP-MIB::netSnmp.2.1.3.0 = Hex-STRING: 68 61 76 65 6E 20 7A 68 61 6F 00 61 
照样失败!

经过反复测试,好像和字符串的长度有关系。改变后的字符串与初始化时的字符串长度不一致时,总是达不到我们想要的效果。是的,问题就出在这里!

解决方案:

看这行代码:watcher_flags = WATCHER_MAX_SIZE; 
就在这个小小的参数上,例子中的WATCHER_MAX_SIZE:variable size (length can be 0 - MAX, for some MAX),If set then the variable data_size_p points to is supposed to hold the current size of the watched object and will be updated on writes. 
而我们则需要这个:c string (length can be 0 - MAX-1 for some max, \0 is not a valid  character in the string, the length is provided by strlen),也就是这个:WATCHER_SIZE_STRLEN

好,马上替换watcher_flags = WATCHER_MAX_SIZE;为watcher_flags = WATCHER_SIZE_STRLEN; 
编译运行,测试: 
输入:snmpget -v1 -c public localhost 1.3.6.1.4.1.8072.2.1.3.0 
返回:NET-SNMP-MIB::netSnmp.2.1.3.0 = STRING: "haven zhao"

OK!到此为止,我们终于前进了一步,由get/set一个int型变量,到get/set一个字符串型变量,而且这个字符串变量,可由外部的代码对其进行设置,从而实现了监测变化的字符串变量的目的。

这只是单个的变量,可能要监测的变量不只一个,那怎么办呢?未完待续:http://vcsky.net

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值