1. 程式人生 > >net-snmp agent開發詳解

net-snmp agent開發詳解

轉載請標明出處 原文地址:http://blog.csdn.net/hepeng597/article/details/8782868

花了一兩天時間測試和整理一下。

用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上開發和測試

一、安裝snmpd

既然要測試,而且我們用的也是net-snmp工具,當然要先安裝snmpd,本文采用5.7.2版本的snmpd,需安裝net-snmp-5.7.2-1, net-snmp-devel-5.7.2-1,net-snmp-perlmods-5.7.2-1,安裝可以是編譯net-snmp的原始碼,也可以下載rpm包安裝,這裡略過。

安裝好後測試一下service snmpd status,如果沒有反應,可能是沒有配置檔案,可以手動建立/etc/snmp目錄,在snmp目錄下建立snmpd.conf檔案,填入一些基本的配置資訊(或者通過snmpconf程式一步一步生成,snmpconf程式比較容易懂,適合童鞋們,snmpconf會提示你建立什麼配置檔案,需不需要把snmpd作為主代理等等強大的提示):

[cpp] view plain copy print?
  1. master agentx  
  2. rocommunity public
  3. rwcommunity public
master agentx
rocommunity public
rwcommunity public

master 是說該snmpd以主代理方式執行,目前主代理snmpd只支援agentx型別,而我們要開發的程式是一種子代理(subagent),是需要連snmpd的master agent的。rocommunity (只讀物件)和rwcommunity(讀寫物件)的密碼都是public.(這個密碼就是客戶端訪問OID時需要提供的密碼,比如在任一一個裝有snmpd的linux機器上,執行snmpwalk -v2c -c public localhost 1.3.6.1.2.1.1, 這裡的public就是密碼,分別有隻讀OID密碼,和讀寫OID密碼),本文測試就以public作為預設的密碼吧。

現在測試一下snmpd是否正常,啟動service snmpd restart,執行snmpwalk -v2c -c public localhost 1.3.6.1.2.1.1, 如果有SNMPv2-MIB:xxxx之類的輸出就表示我們的主代理已經工作了。

二、自己的MIB庫

首先MIB庫有什麼用?其實作為子代理來說,在server機器上,可以不用MIB庫,MIB庫只為了讓使用者訪問時方便,有了MIB庫,使用者就不用記那麼多和長的OID,比如把MIB放在windows機器上,在windows機器裝一個支援MIB的軟體,用該軟體開啟MIB庫,只要點選相應的物件就可以自動傳送snmp請求到server端,所以server端是可以不要MIB庫的。如果把MIB庫放在linux客戶端機器上,以下面自定義的MIB庫為例,那麼就可以直接執行snmpget -v2c -c public Test-MIB::GetTime.0,當然需要linux客戶端裝有snmp,而且自定義的MIB庫必須能讓snmpd程式找到。 

這裡用就一個OID建一個MIB庫來簡化,命名Test-MIB.my,放在/usr/local/share/snmp/mibs目錄下,因為這個目錄是snmpd的預設目錄,只要把MIB庫放入該目錄就可以自動載入MIB庫,否則需要修改/etc/snmp/snmp.conf檔案,新增mibs +/path/to/Test-MIB.my 並重啟snmpd。

自定義MIB庫,如下:

[cpp] view plain copy print?
  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  
-- Test-MIB.my
    Test-MIB DEFINITIONS ::= BEGIN

        IMPORTS
            OBJECT-GROUP, MODULE-COMPLIANCE, NOTIFICATION-GROUP    
                FROM SNMPv2-CONF    
            enterprises, Integer32, Unsigned32, OBJECT-TYPE, MODULE-IDENTITY, 
            NOTIFICATION-TYPE    
                FROM SNMPv2-SMI    
            DisplayString    
                FROM SNMPv2-TC;

-- October 09, 2002 at 14:50 GMT
        -- 1.3.6.1.4.1.16535
        Test MODULE-IDENTITY 
            LAST-UPDATED "200210091450Z"        -- October 09, 2002 at 14:50 GMT
            ORGANIZATION 
                ""  
            CONTACT-INFO 
                ""  
            DESCRIPTION 
                "Video's Server MIB."
            ::= { enterprises 16535 }

--  Node definitions
-- This part will include all details about the Test.
        -- 1.3.6.1.4.1.16535.1
        Time OBJECT IDENTIFIER ::= { Test 1 } 


        -- 1.3.6.1.4.1.16535.1.1
        GetTime OBJECT-TYPE
            SYNTAX DisplayString (SIZE (0..100))
            MAX-ACCESS read-only
            STATUS current
            DESCRIPTION
                "Example : 2013/4/11"
            ::= { Time 1 }
    END

-- Test-MIB.my

很簡單,該MIB庫只有一個OID,即:1.3.6.1.4.1.16535.1.1,寫完後我們測一個MIB庫有沒有問題,在linux機器上用snmptranslate -Tp -IR Test-MIB::Test顯示結果如下:

[plain] view plain copy print?
  1. +–Test(16535)  
  2.    |  
  3.    +–Time(1)  
  4.       |  
  5.       +– -R– String    GetTime(1)  
  6.                Textual Convention: DisplayString  
  7.                Size: 0..100  
+--Test(16535)
   |
   +--Time(1)
      |
      +-- -R-- String    GetTime(1)
               Textual Convention: DisplayString
               Size: 0..100

OK, snmp自動發現了這個MIB庫, 有了自定義的OID,但是還沒有處理程式(子代理)

三、生成原始碼

mib2c可以根據mib庫生成對應的原始碼,有多種模板,這裡我們要生成子代理的程式碼,所以選擇是固定的,執行env MIBS=”+/usr/local/share/snmp/mibs/Test-MIB.my” mib2c Test,會引導你逐漸生成Test.h和Test.c, 先選2再選1,過程如下:

[plain] view plain copy print?
  1. [[email protected] mibs]# env MIBS=”+/etc/snmp/mibs/Test-MIB.my” mib2c Test  
  2. writing to -  
  3. mib2c has multiple configuration files depending on the type of  
  4. code you need to write.  You must pick one depending on your need.  
  5. You requested mib2c to be run on the following part of the MIB tree:  
  6.   OID:                              Test  
  7.   numeric translation:              .1.3.6.1.4.1.16535  
  8.   number of scalars within:         1     
  9.   number of tables within:          0     
  10.   number of notifications within:   0     
  11. First, do you want to generate code that is compatible with the   
  12. ucd-snmp 4.X line of code, or code for the newer Net-SNMP 5.X code  
  13. base (which provides a much greater choice of APIs to pick from):  
  14.   1) ucd-snmp style code  
  15.   2) Net-SNMP style code  
  16. Select your choice : 2   
  17. **********************************************************************  
  18.          GENERATING CODE FOR SCALAR OBJECTS:  
  19. **********************************************************************  
  20.   It looks like you have some scalars in the mib you requested, so I  
  21.   will now generate code for them if you wish.  You have two choices  
  22.   for scalar API styles currently.  Pick between them, or choose not   
  23.   to generate any code for the scalars:  
  24.   1) If you’re writing code for some generic scalars  
  25.      (by hand use: “mib2c -c mib2c.scalar.conf Test”)  
  26.   2) If you want to magically “tie” integer variables to integer  
  27.      scalars  
  28.      (by hand use: “mib2c -c mib2c.int_watch.conf Test”)  
  29.   3) Don’t generate any code for the scalars  
  30. Select your choice: 1  
  31.     using the mib2c.scalar.conf configuration file to generate your code.  
  32. writing to Test.h  
  33. writing to Test.c  
  34. **********************************************************************  
  35. * NOTE WELL: The code generated by mib2c is only a template.  *YOU*  *  
  36. * must fill in the code before it’ll work most of the time.  In many *  
  37. * cases, spots that MUST be edited within the files are marked with  *  
  38. * /* XXX */ or /* TODO */ comments.                                  *  
  39. **********************************************************************  
  40. running indent on Test.h  
  41. running indent on Test.c  
[[email protected] mibs]# env MIBS="+/etc/snmp/mibs/Test-MIB.my" mib2c Test
writing to -
mib2c has multiple configuration files depending on the type of
code you need to write.  You must pick one depending on your need.

You requested mib2c to be run on the following part of the MIB tree:
  OID:                              Test
  numeric translation:              .1.3.6.1.4.1.16535
  number of scalars within:         1   
  number of tables within:          0   
  number of notifications within:   0   

First, do you want to generate code that is compatible with the 
ucd-snmp 4.X line of code, or code for the newer Net-SNMP 5.X code
base (which provides a much greater choice of APIs to pick from):

  1) ucd-snmp style code
  2) Net-SNMP style code

Select your choice : 2 

**********************************************************************
         GENERATING CODE FOR SCALAR OBJECTS:
**********************************************************************

  It looks like you have some scalars in the mib you requested, so I
  will now generate code for them if you wish.  You have two choices
  for scalar API styles currently.  Pick between them, or choose not 
  to generate any code for the scalars:

  1) If you're writing code for some generic scalars
     (by hand use: "mib2c -c mib2c.scalar.conf Test")

  2) If you want to magically "tie" integer variables to integer
     scalars
     (by hand use: "mib2c -c mib2c.int_watch.conf Test")

  3) Don't generate any code for the scalars

Select your choice: 1
    using the mib2c.scalar.conf configuration file to generate your code.
writing to Test.h
writing to Test.c



**********************************************************************
* NOTE WELL: The code generated by mib2c is only a template.  *YOU*  *
* must fill in the code before it'll work most of the time.  In many *
* cases, spots that MUST be edited within the files are marked with  *
* /* XXX */ or /* TODO */ comments.                                  *
**********************************************************************
running indent on Test.h
running indent on Test.c
mib2c已經統計出我們的mib庫包含1個scalar變數,0個table變數,0個通知變數,Scalar就是包含我們常用的整型,字串,時間等等資料型別。table就是scalar的一種集合,有一個和多個列組成,類似於資料庫中的表。它必須具有索引項,用來按一定順序檢索表項,當然我們只寫了一個標量的OID,不是表結構也不是通知結構

生成的Test.h如下:

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




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





#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 GetTime_oid[] = { 1, 3, 6, 1, 4, 1, 16535, 1, 1 }; DEBUGMSGTL(("Test", "Initializing\n")); netsnmp_register_scalar(netsnmp_create_handler_registration ("GetTime", handle_GetTime, GetTime_oid, OID_LENGTH(GetTime_oid), HANDLER_CAN_RONLY)); } int handle_GetTime(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_OCTET_STR, /* * 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_GetTime\n", reqinfo->mode); return SNMP_ERR_GENERR; } return SNMP_ERR_NOERROR; }

以上的程式碼都是自動生成的,我們沒有寫一行程式碼,到了這一步,我們需要把Test.c裡面的 XXX改成自己的值,也就兩行,修改後Test.c檔案程式碼如下:

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





#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" #include <time.h> /** Initializes the Test module */ void init_Test(void) { const oid GetTime_oid[] = { 1, 3, 6, 1, 4, 1, 16535, 1, 1 }; DEBUGMSGTL(("Test", "Initializing\n")); netsnmp_register_scalar(netsnmp_create_handler_registration ("GetTime", handle_GetTime, GetTime_oid, OID_LENGTH(GetTime_oid), HANDLER_CAN_RONLY)); } int handle_GetTime(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. */ time_t t; switch (reqinfo->mode) { case MODE_GET: time(&t); char szTime[100]; snprintf(szTime,100,"%s",ctime(&t)); snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR, /* * XXX: a pointer to the scalar's data */ szTime, /* * XXX: the length of the data in bytes */ strlen(szTime)); break; default: /* * we should never get here, so this is a really bad error */ snmp_log(LOG_ERR, "unknown mode (%d) in handle_GetTime\n", reqinfo->mode); return SNMP_ERR_GENERR; } return SNMP_ERR_NOERROR; }簡單吧,現在子代理程式基本就寫完了,我們執行命令讓我們的子代理生成可執行程式,執行

net-snmp-config –compile-subagent Test Test.c,生成了Test程式, 執行過程如下:



可以看出來,net-snmp-config程式生成了一個臨時的C檔案,netsnmptmp.12373.c 並與Test.c一起編譯,生成了Test程式後又刪除了該臨時檔案。我們會在最後研究netsnmptmp.12373.c檔案。

四、測試一下

現在Test程式已經生成了,我們先執行主代理(service snmpd start),再執行子代理./Test,再ps -ef | grep Test,看一下,可以看到Test程式自動在後臺啟動了,如下:

[plain] view plain copy print?
  1. [[email protected] hepeng]# ps -ef| grep Test   
  2. root     27526     1  0 13:29 ?        00:00:00 ./Test  
  3. root     27531 27448  0 13:29 pts/2    00:00:00 grep Test  
[[email protected] hepeng]# ps -ef| grep Test 
root     27526     1  0 13:29 ?        00:00:00 ./Test
root     27531 27448  0 13:29 pts/2    00:00:00 grep Test
到這裡我們可以想象到,Test.c檔案中是沒有main函式的,那麼main函式肯定是在netsnmptmp.12373.c 中,net-snmp-config讓Test程式變成了守護程序在後臺執行。

到此我們的service端就已經佈置完成了,子代理理論上可以回覆自定義的GetTime OID的請求。

本文在一臺裝有snmpd和子代理的linux server機器上直接測試。執行命令如下:

[plain] view plain copy print?
  1. [[email protected] hepeng]# snmpget -v2c -c public localhost 1.3.6.1.4.1.16535.1.1.0  
  2. SNMPv2-SMI::enterprises.16535.1.1.0 = STRING: “Thu Apr 11 13:40:20 2013  
  3. “  
[[email protected] hepeng]# snmpget -v2c -c public localhost 1.3.6.1.4.1.16535.1.1.0
SNMPv2-SMI::enterprises.16535.1.1.0 = STRING: "Thu Apr 11 13:40:20 2013
"
可以看到,我們開發的子代理成功工作了。如果自定義的MIB庫已經加入到snmpd指定的目錄中,我們可以執行 [plain] view plain copy print?
  1. [[email protected] ~]&nbsp;snmpget&nbsp;-v2c&nbsp;-c&nbsp;public&nbsp;localhost&nbsp;Test-MIB:GetTime.0&nbsp;&nbsp;</span></span></li><li class=""><span>Test-MIB::GetTime.0&nbsp;=&nbsp;STRING:&nbsp;Thu&nbsp;Apr&nbsp;11&nbsp;13:46:42&nbsp;2013&nbsp;&nbsp;</span></li></ol></div><pre code_snippet_id="147799" snippet_file_name="blog_20140108_10_4114675" name="code" class="plain" style="display: none;">[[email protected] ~] snmpget -v2c -c public localhost Test-MIB:GetTime.0 Test-MIB::GetTime.0 = STRING: Thu Apr 11 13:46:42 2013snmpget會自動在所有的MIB庫中查詢Test-MIB庫,並把Test-MIB:GetTime.0轉換成1.3.6.1.4.1.16535.1.1.0併發送get請求。

    現在子代理是已經開發成功了,我們實際上只寫了兩三行程式碼就開發了net-snmp子代理,是不是很簡單呢?

    現在有個問題,怎麼加入到我們自己的專案中呢?因為Test.c中並沒有main函式,在一個專案中直接呼叫init_Test()能不能讓子代理work呢?那就要研究一下netsnmptmp.12373.c。

    五、加入專案中

    我們再次執行net-snmp-config –compile-subagent Test Test.c,然後立刻Ctrl+c,時間要控制好,讓net-snmp-config程式產生了臨時的C檔案,卻沒有刪除它。開啟netsnmptmp.12373.c,我們來看一下程式碼,200多行,本文只貼上main函式的重要部分,程式碼中都添加了註釋,不難理解:

    [cpp] view plain copy print?
    1. int main (int argc, char **argv)  
    2. {  
    3.   int arg;  
    4.   char* cp = NULL;  
    5.   int dont_fork = 0, do_help = 0;  
    6.   while ((arg = getopt(argc, argv, “dD:fhHL:”
    7. #ifndef DISABLE_MIB_LOADING
    8.                        ”m:M:”
    9. #endif /* DISABLE_MIB_LOADING */
    10.                        ”n:”
    11. #ifndef DISABLE_MIB_LOADING
    12.                        ”P:”
    13. #endif /* DISABLE_MIB_LOADING */
    14.                        ”vx:”)) != EOF) {  
    15.     switch (arg) {  
    16.     case‘D’:/*這裡省略多個case break,只是一些選項,沒必要研究/ 
    17.       break; 
    18.     default: 
    19.       fprintf(stderr, “invalid option: -%c\n”, arg); 
    20.       usage(argv[0]); 
    21.       break; 
    22.     } 
    23.   } 
    24.   if (do_help) { 
    25.     netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 
    26.                            NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1); 
    27.   } else { 
    28.     /* we are a subagent  第一步:這裡是告訴snmpd我們這個Test作為子代理*/
    29.     netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,  
    30.                            NETSNMP_DS_AGENT_ROLE, 1);  
    31.     if (!dont_fork) {/* 這裡是讓Test程式變成守護程序,執行Test後可以在後臺執行不會退出 */
    32.       if (netsnmp_daemonize(1, snmp_stderrlog_status()) != 0)  
    33.         exit(1);  
    34.     }  
    35.     /* initialize tcpip, if necessary */
    36.     SOCK_STARTUP;  
    37.   }  
    38.   /* initialize the agent library 第二步*/
    39.   init_agent(app_name);  
    40.   /* initialize your mib code here 第三步*/
    41.   init_Test();  
    42.   /* Test will be used to read Test.conf files. 第四步 */
    43.   init_snmp(”Test”);  
    44.   if (do_help) {  
    45.     fprintf(stderr, ”Configuration directives understood:\n”);  
    46.     read_config_print_usage(”  ”);  
    47.     exit(0);  
    48.   }  
    49.   /* In case we received a request to stop (kill -TERM or kill -INT) */
    50.   netsnmp_running = 1;  
    51. #ifdef SIGTERM
    52.   signal(SIGTERM, stop_server);  
    53. #endif
    54. #ifdef SIGINT
    55.   signal(SIGINT, stop_server);  
    56. #endif
    57. #ifdef SIGHUP
    58.   signal(SIGHUP, hup_handler);  
    59. #endif
    60.   /* main loop here… */
    61.   while(netsnmp_running) {  
    62.     if (reconfig) {  
    63.       free_config();  
    64.       read_configs();  
    65.       reconfig = 0;  
    66.     }  
    67.     agent_check_and_process(1);  
    68.   }  
    69.   /* at shutdown time */
    70.   snmp_shutdown(app_name);  
    71.   /* deinitialize your mib code here */
    72.   /* shutdown the agent library */
    73.   shutdown_agent();  
    74.   SOCK_CLEANUP;  
    75.   exit(0);  
    76. }  
    int main (int argc, char **argv)
    {
      int arg;
      char* cp = NULL;
      int dont_fork = 0, do_help = 0;
    
      while ((arg = getopt(argc, argv, "dD:fhHL:"
    
    
    
    
    
#ifndef DISABLE_MIB_LOADING "m:M:" #endif /* DISABLE_MIB_LOADING */ "n:" #ifndef DISABLE_MIB_LOADING "P:" #endif /* DISABLE_MIB_LOADING */ "vx:")) != EOF) { switch (arg) { case 'D':/*這裡省略多個case break,只是一些選項,沒必要研究/ break; default: fprintf(stderr, "invalid option: -%c\n", arg); usage(argv[0]); break; } } if (do_help) { netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1); } else { /* we are a subagent 第一步:這裡是告訴snmpd我們這個Test作為子代理*/ netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1); if (!dont_fork) {/* 這裡是讓Test程式變成守護程序,執行Test後可以在後臺執行不會退出 */ if (netsnmp_daemonize(1, snmp_stderrlog_status()) != 0) exit(1); } /* initialize tcpip, if necessary */ SOCK_STARTUP; } /* initialize the agent library 第二步*/ init_agent(app_name); /* initialize your mib code here 第三步*/ init_Test(); /* Test will be used to read Test.conf files. 第四步 */ init_snmp("Test"); if (do_help) { fprintf(stderr, "Configuration directives understood:\n"); read_config_print_usage(" "); exit(0); } /* In case we received a request to stop (kill -TERM or kill -INT) */ netsnmp_running = 1; #ifdef SIGTERM signal(SIGTERM, stop_server); #endif #ifdef SIGINT signal(SIGINT, stop_server); #endif #ifdef SIGHUP signal(SIGHUP, hup_handler); #endif /* main loop here... */ while(netsnmp_running) { if (reconfig) { free_config(); read_configs(); reconfig = 0; } agent_check_and_process(1); } /* at shutdown time */ snmp_shutdown(app_name); /* deinitialize your mib code here */ /* shutdown the agent library */ shutdown_agent(); SOCK_CLEANUP; exit(0); }
我們不管上面程式碼那些看不懂的函式,知道大概意思就行,現在我們來加入到自己的專案中,找到專案中的main函式,在main函式中新增初始化Test子代理的程式碼,本文為了方便理解,就在Test.c中新增main函式,就地取材,寫個超簡單函式,不考慮傳入引數。修改後的Test.c檔案如下: [cpp] view plain copy print?
  1. /* 
  2.  * Note: this file originally auto-generated by mib2c using 
  3.  *        $ 
  4.  */
  5. #include <net-snmp/net-snmp-config.h>
  6. #include <net-snmp/net-snmp-includes.h>
  7. #include <net-snmp/agent/net-snmp-agent-includes.h>
  8. #include “Test.h”
  9. #include <time.h>
  10. /** Initializes the Test module */
  11. void
  12. init_Test(void)  
  13. {  
  14.     const oid       GetTime_oid[] = { 1, 3, 6, 1, 4, 1, 16535, 1, 1 };  
  15.     DEBUGMSGTL((”Test”“Initializing\n”));  
  16.     netsnmp_register_scalar(netsnmp_create_handler_registration  
  17.                             (”GetTime”, handle_GetTime, GetTime_oid,  
  18.                              OID_LENGTH(GetTime_oid), HANDLER_CAN_RONLY));  
  19. }  
  20. int
  21. handle_GetTime(netsnmp_mib_handler *handler,  
  22.                netsnmp_handler_registration *reginfo,  
  23.                netsnmp_agent_request_info *reqinfo,  
  24.                netsnmp_request_info *requests)  
  25. {  
  26.     /* 
  27.      * We are never called for a GETNEXT if it’s registered as a 
  28.      * “instance”, as it’s “magically” handled for us.   
  29.      */
  30.     /* 
  31.      * a instance handler also only hands us one request at a time, so 
  32.      * we don’t need to loop over a list of requests; we’ll only get one.  
  33.      */
  34.     time_t t;  
  35.     switch (reqinfo->mode) {  
  36.     case MODE_GET:  
  37.     time(&t);  
  38.     char szTime[100];  
  39.     snprintf(szTime,100,”%s”,ctime(&t));  
  40.         snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,  
  41.                                  /* 
  42.                                   * XXX: a pointer to the scalar’s data  
  43.                                   */ szTime,  
  44.                                  /* 
  45.                                   * XXX: the length of the data in bytes  
  46.                                   */ strlen(szTime));  
  47.         break;  
  48.     default:  
  49.         /* 
  50.          * we should never get here, so this is a really bad error  
  51.          */
  52.         snmp_log(LOG_ERR, ”unknown mode (%d) in handle_GetTime\n”,  
  53.                  reqinfo->mode);  
  54.         return SNMP_ERR_GENERR;  
  55.     }  
  56.     return SNMP_ERR_NOERROR;  
  57. }  
  58. staticint keep_running;  
  59. RETSIGTYPE stop_server(int __attribute__((unused)) a) {  
  60.         keep_running = 0;  
  61. }  
  62. int main()  
  63. {  
  64.    

    相關推薦

    net-snmp agent開發,非常簡單

    轉載請標明出處 原文地址:http://blog.csdn.net/hepeng597/article/details/8782868 花了一兩天時間測試和整理一下。 用net-snmp擴充套件MIB庫,實現方法可歸結為四種: 1)一是靜態庫方式,通過修改配置標頭檔案,

    net-snmp agent開發

    轉載請標明出處 原文地址:http://blog.csdn.net/hepeng597/article/details/8782868 花了一兩天時間測試和整理一下。 用net-snmp擴充套件MIB庫,實現方法可歸結為四種: 1)一是靜態庫方式,通

    基於net-snmp的代理agent開發

    花了一兩天時間測試和整理一下。 用net-snmp擴充套件MIB庫,實現方法可歸結為四種: 1)一是靜態庫方式,通過修改配置標頭檔案,在相應地方包含新引入的mib模組的.c和.h檔案,然後重新編譯庫檔案和擴充套件程式碼;這種方式不夠靈活,每次修改擴

    【轉】Quartz.net持久化與集群部署開發

    疑惑 sum 常用 drive wid res net github hub 轉自:http://www.cnblogs.com/knowledgesea/p/5145239.html 序言 我前邊有幾篇文章有介紹過quartz的基本使用語法與類庫。但是他的執行計劃都是被寫

    Vue.js 插件開發

    js 前言隨著 Vue.js 越來越火,Vue.js 的相關插件也在不斷的被貢獻出來,數不勝數。比如官方推薦的 vue-router、vuex 等,都是非常優秀的插件。但是我們更多的人還只停留在使用的階段,比較少自己開發。所以接下來會通過一個簡單的 vue-toast 插件,來了解掌握插件的開發和使用。

    斑布生活家系統開發模式設計

    log 所有 http 裏的 詳解 啟動 一次 什麽 氣體 斑布生活家系統開發(李想.185.6504.8478)根據化石研究,史前時代的始祖鳥被認為是最早的飛行鳥類,它在許多方面已顯現鳥的一些雛形,例如全身長有羽毛和翅膀、具有明顯的叉骨等。這些證據表明,鳥類的飛行能力應該

    Asp.Net MVC3 簡單入門過濾器Filter

    添加 重復 權限 組件 再次 ace text ext 開發 前言 在開發大項目的時候總會有相關的AOP面向切面編程的組件,而MVC(特指:Asp.Net MVC,以下皆同)項目中不想讓MVC開發人員去關心和寫類似身份驗證,日誌,異常,行為截取等這部分重復的代碼,那我們可以

    Hive UDAF開發

    -s 聚合 而且 pri ros cal 關系 方法調用 evaluator 明這篇文章是來自Hadoop Hive UDAF Tutorial - Extending Hive with Aggregation Functions:的不嚴格翻譯,因為翻譯的文章示例寫得比較

    ADO.NET五大對象

    支持 數據庫 asp 增刪改 eno 打開 sql man let Connection 連接對象Command 命令對象,指示要執行的命令和存儲過程! DataReader是一個向前的只讀的數據流。 DataAdapter是功能強大的適配合器,支持增刪改查的功能 Data

    asp.net程序發布

    存在 mage com 環境 整體 cnblogs 配置 轉載 系列 本文轉載自Alan_beijing的博客ASP.NET 程序發布詳細過程。內容進行了部分更改。 ASP.NET網站的發布,無論是初學者還是高手,在程序的發布過程中或多或少會存在一些問題,譬如VS發布AS

    果園農場種植遊戲復利拆分模式app系統開發

    計算 數量 政策 經營者 終端 默認 自己 產生 後臺 330復利拆分果園遊戲app系統開發(蘇公子.188.1414.7927)皮皮果遊戲開發,玫瑰莊園遊戲開發,復利拆分遊戲開發,330模式開發,330果園系統開發,復利拆分農場系統開發,英倫果開發,皮皮果遊戲介紹,地點的

    火爆的車享家模式系統開發

    目前 聯合體 移動互聯網 體系 通過 系列 獲得 com img 車享家是一個關於用車的全方位平臺!上線至今都十分火熱,盈利能力也強,通過結合“高效線上運營”和“優質線下服務”,全方位打通汽車“看、選、買、用、賣”,簡單來看,是淘寶+o2o的聯合體。目前汽車市場蓬勃發展,汽

    Android"掛逼"修煉之行---微信中定位照片的位置信息插件開發

    頁面 blank 如果 put 法律 mali 特殊字符 在哪裏 加載 一、前言 最近關於微信中,朋友之間發送原圖就可能暴露你的位置信息,其實這個問題不在於微信,微信是為了更好的體驗效果,才有發送原圖功能,而對於拍照,發送普通圖片微信後臺都會過濾圖片的exif信息,這樣就

    android黑科技系列——微信定位聊天記錄中照片的位置信息插件開發

    poi 圖片查看 遍歷 什麽 term 反射 還需要 資料 避免 一、前言 最近關於微信中,朋友之間發送原圖就可能暴露你的位置信息,其實這個問題不在於微信,微信是為了更好的體驗效果,才有發送原圖功能,而對於拍照,發送普通圖片微信後臺都會過濾圖片的exif信息,這樣就不會攜

    PHP與Java集成開發(一)

    new 編程語言 到你 其中 web-inf request 測試 add 輸入 很久以前,有人從www上看到看到天空上一個很亮的亮點,它就是Java語言,與此同時,在另一個地方一位夢想家也看到了一個亮點,它就是PHP。 時間一天天過去,這兩個亮點也變得越來越亮,很快,它

    【轉】Android Camera 相機開發

    exc troy start 當前 container rac google getconf 對比度 在Android 5.0(SDK 21)中,Google使用Camera2替代了Camera接口。Camera2在接口和架構上做了巨大的變動, 但是基於眾所周知的原因

    net user命令集合

    itl 停止 字典 shel 終端服務 sca 主機名 網絡連接類型 漏洞 net user命令集合詳解 net use \\ip\ipc$ " " /user:" " 建立IPC空鏈接 net use \\ip\ipc$ "密碼" /user:"用戶名" 建立IPC非

    HTML5+Canvas開發(第2版).pdf

    繪圖 blog ipa img script 必備 交互式 src 教程 通過HTML5+Canvas開發詳解(第2版),你將學到如何使用Canvas進行繪圖、渲染文字、處理圖像、創建動畫,而這些是開發交互式Web遊戲的必備知識。 本書針對Canvas和HTML5技

    Java中的OA信用盤源碼開發

    直接 所有 stat 開始 println printf void 一個 [] 首先先創建一個打印數組的方法,OA信用盤源碼開發(企 娥:217 1793 408)方便後面直接使用 public static void output(int []a) {for(int i=

    安裝Cloudera manager agent步驟

    安裝包 記錄 style 繼續 作者 manage gen -s png              安裝Cloudera manager agent步驟詳解                                         作者:尹正傑 版權聲明:原創作品,謝