snmp-agentの初歩的な理解

49593 ワード

入門レベルのsnmp agent開発は、この文章を通じてsnmp agentの開発構想を大まかに理解することができ、主にネットブログと公式ドキュメントを参考にし、下にリンクがあります.
Net-snmpでMIBライブラリを拡張すると、実装方法は4つにまとめることができます.
1)静的ライブラリ方式は,ヘッダファイルを修正することにより,新たに導入するmibモジュールを該当箇所に含める.c和.hファイルを再コンパイルし、ライブラリファイルと拡張コードを再コンパイルします.この方式は柔軟ではなく,拡張MIBを修正するたびにsnmpdと拡張コードを再コンパイルし,snmpdをシステムに再インストールする必要がある.
2)二つ目は動的共有ライブラリをコンパイルし,新たに導入したMIBモジュールのみをコンパイルすることである.c和.hファイルはダイナミックライブラリにコンパイルされ,設定によりエージェントをロードできる.
第2の態様については、1つはコンパイルする必要がある.soダイナミック共有ライブラリ、2元のエージェントにdlmodまたはloadコマンドが含まれているかどうか、3システムがサポートされているかどうかを確認します.一般的にUnixプラットフォームのみがサポートされています.
3)三つ目はサブエージェントを拡張し、SNMPDをメインエージェントのモードで実行させることであり、SNMPDに対しては起動させるだけで、変更や構成を必要とせず、サブエージェントコンパイルによって生成されたプログラムを実行すればカスタムMIBライブラリを拡張することができる.
4)shell脚で本来広げる
本文は第3の方法でlinuxの上で開発してテストします
一、snmpdのインストール
1.1インストールパッケージ:
net-snmp-agent-libs-5.7.2-28.el7_4.1.x86_64
net-snmp-utils-5.7.2-28.el7_4.1.x86_64
net-snmp-libs-5.7.2-28.el7_4.1.x86_64
net-snmp-5.7.2-28.el7_4.1.x86_64
net-snmp-devel-5.7.2-28.el7_4.1.x86_64
net-snmp-perl-5.7.2-28.el7_4.1.x86_64

1.2テスト
systemctl restart snmpd.service
systemctl status snmpd.service
#    running       

1.3構成vim /etc/snmp/snmpd.conf
master agentx  # master    snmpd        

rocommunity public  # rocommunity (    )

rwcommunity public  # rwcommunity(    )

デフォルトのプライマリエージェントsnmpdはagentxタイプのみをサポートしますが、開発するプログラムはsubagentであり、snmpdのmaster agentに接続する必要があります.
snmpdが正常かどうかをテストします
実行snmpwalk -v2c -c public localhost 1.3.6.1.2.1.1
出力は以下のように表示され、正常に動作していることを示します.
SNMPv2-MIB::sysDescr.0 = STRING: Linux bogon 3.10.0-693.el7.x8664 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x8664

二、MIBライブラリ
まずMIBライブラリは何の役に立ちますか?実はサブエージェントとして、serverマシンの上で、MIBライブラリを使わなくてもいいです.MIBライブラリはユーザーがアクセスできるようにするためだけに、MIBライブラリがあれば、ユーザーはそんなに多くて長いOIDを覚える必要はありません.例えば、MIBをwindowsマシンの上に置いて、windowsマシンにMIBをサポートするソフトウェアをインストールして、このソフトウェアでMIBライブラリを開きます.該当するオブジェクトをクリックするだけで自動的にsnmpリクエストをサーバ側に送信できるので、サーバ側はMIBライブラリを不要にすることができます.
MIB格納ディレクトリ/usr/share/snmp/mibsのディレクトリの下で、このディレクトリはsnmpdのデフォルトディレクトリであるため、MIBライブラリをそのディレクトリに入れるだけで自動的にMIBライブラリをロードすることができ、そうでなければ/etc/snmp/snmpを変更する必要がある.confファイル、mibs+/path/to/XXXを追加し、snmpdを再起動します.
2.1例1
カスタムMIBライブラリ:
-- 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ライブラリには、1つのOID、すなわち、1.3しかない.6.1.4.1.16535.1.1
テスト:
snmptranslate -Tp -IR Test-MIB::Test
#        ,  MIB    
+--Test(16535)
   |
   +--Time(1)
      |
      +-- -R-- String    GetTime(1)
               Textual Convention: DisplayString
               Size: 0..100

2.1例2
NET-SNMP-UTORAL-MIBを公式に提供します.txt
NET-SNMP-TUTORIAL-MIB DEFINITIONS ::= BEGIN

-- A Comment!

-- IMPORTS: Include definitions from other mibs here, which is always
-- the first item in a MIB file.
IMPORTS
    netSnmpExamples                   FROM NET-SNMP-EXAMPLES-MIB
    OBJECT-TYPE, Integer32,
    MODULE-IDENTITY                       FROM SNMPv2-SMI
    MODULE-COMPLIANCE, OBJECT-GROUP       FROM SNMPv2-CONF;

--
-- A brief description and update information about this mib.
--
netSnmpTutorialMIB MODULE-IDENTITY
    LAST-UPDATED "200205290000Z"            -- 29 May 2002, midnight
    ORGANIZATION "net-snmp"
    CONTACT-INFO "postal:   Wes Hardaker
                            P.O. Box 382
                            Davis CA  95617

          email:    [email protected]
                 "
    DESCRIPTION  "A simple mib for demonstration purposes.
                 "
    ::= { netSnmpExamples 4 }

-- Define typical mib nodes, like where the objects are going to lie.
-- we'll prefix everything in this mib with nst (net snmp tutorial)
nstMIBObjects     OBJECT IDENTIFIER ::= { netSnmpTutorialMIB 1 }
nstMIBConformance OBJECT IDENTIFIER ::= { netSnmpTutorialMIB 2 }


-- define 3 objects, which will all be implemented in different ways
-- within the tutorial.

nstAgentModules   OBJECT IDENTIFIER ::= { nstMIBObjects 1 }


nstAgentModuleObject OBJECT-TYPE
    SYNTAX      Integer32
    MAX-ACCESS  read-write
    STATUS      current
    DESCRIPTION
    "This is an object that simply supports a writable integer
     when compiled into the agent.  See
     http://www.net-snmp.org/tutorial-5/toolkit/XXX for further
     implementation details."
    DEFVAL { 1 }
    ::= { nstAgentModules 1 }

nstAgentSubagentObject OBJECT-TYPE
    SYNTAX      Integer32
    MAX-ACCESS  read-write
    STATUS      current
    DESCRIPTION
    "This is an object that simply supports a writable integer
     when attached to the agent.  The object should be accessible
     when the agentx subagent containing this object is attached.
     See http://www.net-snmp.org/tutorial-5/toolkit/XXX for
     further implementation details."
    DEFVAL { 2 }
    ::= { nstAgentModules 2 }

nstAgentPluginObject OBJECT-TYPE
    SYNTAX      Integer32
    MAX-ACCESS  read-write
    STATUS      current
    DESCRIPTION
    "This is an object that simply supports a writable integer
     when attached to the agent.  This object should be accessible
     when the dynamic plugin has been loaded into the agent.  See
     http://www.net-snmp.org/tutorial-5/toolkit/XXX for further
     implementation details."
    DEFVAL { 3 }
    ::= { nstAgentModules 3 }

--
-- The above definitions produce a section of the mib tree that looks
-- like this (including our parent node, printed using the
-- snmptranslate command):
--
--
-- % snmptranslate -M+. -mNET-SNMP-TUTORIAL-MIB -Tp -IR netSnmpTutorialMIB
-- +-netSnmpTutorialMIB(4)
--   |
--   +-nstMIBObjects(1)
--   | |
--   | +-nstAgentModules(1)
--   |   |
--   |   +- -RW- Integer32 nstAgentModuleObject(1)
--   |   +- -RW- Integer32 nstAgentSubagentObject(2)
--   |   +- -RW- Integer32 nstAgentPluginObject(3)
--   |
--   +-nstMIBConformance(2)


-- You can then use the snmptranslate command to get the numerical or
-- textual OID representation of any piece of the tree:


-- Getting a OID:
--   % snmptranslate -M+. -mNET-SNMP-TUTORIAL-MIB -IR nstSSSecondsSinceChanged
--   .1.3.6.1.4.1.2021.13.4242.1.1.2


-- Getting a textual OID:
--   % snmptranslate -On -M+. -mNET-SNMP-TUTORIAL-MIB -IR nstSSSecondsSinceChanged
--   enterprises.ucdavis.ucdExperimental.netSnmpTutorialMIB.nstMIBObjects.nstScalarSet.nstSSSecondsSinceChanged


-- Getting a description:
--   % snmptranslate -Td -M+. -mNET-SNMP-TUTORIAL-MIB -IR nstSSSecondsSinceChanged 
--   .1.3.6.1.4.1.2021.13.4242.1.1.2
--   SYNTAX  TimeTicks
--   UNITS   "1/100th Seconds"
--   MAX-ACCESS      read-only
--   STATUS  current
--   DESCRIPTION     "This object indicates the number of 1/100th seconds since the
--           nstSSSimpleString object has changed.  If it is has never been
--           modified, it will be the time passed since the start of the
--           agent."



-- END:  Don't forget this!
END

このとき我々はカスタムOIDを持っているが,まだハンドラ(サブエージェント)がない.
三、ソースコードの生成
mib 2 cはPERLスクリプトの作成です.PERLがSNMPをサポートするために、PERL CPAN FOR SNMPのパッケージをダウンロードする必要があります.
3.1例1
mib 2 cはmibライブラリに基づいて対応するソースコードを生成することができ、複数のテンプレートがあり、ここではサブエージェントのコードを生成するので、選択は固定され、env MIBS="+/usr/share/snmp/mibs/Test-MIBを実行する.my"mib 2 c Testは、徐々にTestを生成するように導きます.hとTestc、先に2を選んでから1を選んで、過程は以下の通りです.
[root@localhost 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  

mib 2 cは、私たちのmibライブラリに1つのscalar変数、0つのtable変数、0つの通知変数が含まれていることを統計しています.Scalarは、私たちがよく使う整数、文字列、時間などのデータ型を含んでいます.tableはscalarの集合であり、データベース内のテーブルに似た1つ以上のカラムから構成されています.テーブル・アイテムを一定の順序で検索するためのインデックス・アイテムが必要です.もちろん、スカラーのOIDは1つしか書かれていません.テーブル構造でも通知構造でもありません.
生成された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
/* 
 * Note: this file originally auto-generated by mib2c using 
 *        $ 
 */  

#include   
#include   
#include   
#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
"
)); 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
"
, reqinfo->mode); return SNMP_ERR_GENERR; } return SNMP_ERR_NOERROR; }

以上のコードはすべて自動的に生成されて、私たちは1行のコードを書いていません.ここまで来たら、Testを必要とします.cの中のXXXは自分の値に変えて、すぐ2行で、改正した后Test.cファイルコードは以下の通りである.
/* 
 * Note: this file originally auto-generated by mib2c using 
 *        $ 
 */  

#include   
#include   
#include   
#include "Test.h"  
#include   

/** Initializes the Test module */  
void  
init_Test(void)  
{  
    const oid       GetTime_oid[] = { 1, 3, 6, 1, 4, 1, 16535, 1, 1 };  

    DEBUGMSGTL(("Test", "Initializing
"
)); 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
"
, reqinfo->mode); return SNMP_ERR_GENERR; } return SNMP_ERR_NOERROR; }

サブエージェントは基本的に書き終わりました.私たちは命令を実行して、私たちのサブエージェントに実行可能なプログラムを生成させ、net-snmp-config --compile-subagent Test Test.cを実行させ、Testプログラムを生成しました.実行過程は以下の通りです.
Net-snmp-configプログラムは一時的なCファイルを生成し、一時的なファイルとTest.cとともにコンパイルし,Testプログラムを生成した後,そのテンポラリファイルを削除した.
3.2テスト
./Test
[root@bogon mibs]# snmpget -v2c -c public localhost 1.3.6.1.4.1.16535.1.1.0 
SNMPv2-SMI::enterprises.16535.1.1.0 = STRING: "Fri Mar 16 11:04:35 2018
"

3.3例2
nstAgentSubagentObject.cファイル
/*
 * Note: this file originally auto-generated by mib2c using
 *        : mib2c.int_watch.conf,v 5.0 2002/04/20 07:30:13 hardaker Exp $
 */

#include 
#include 
#include 
#include "nstAgentSubagentObject.h"

/*
 * the variable we want to tie an OID to.  The agent will handle all
 * * GET and SET requests to this variable changing it's value as needed.
 */

static long      nstAgentSubagentObject = 2;

/*
 * our initialization routine, automatically called by the agent 
 * (to get called, the function name must match init_FILENAME()) 
 */
void
init_nstAgentSubagentObject(void)
{
    static oid      nstAgentSubagentObject_oid[] =
        { 1, 3, 6, 1, 4, 1, 8072, 2, 4, 1, 1, 2, 0 };

    /*
     * a debugging statement.  Run the agent with -DnstAgentSubagentObject to see
     * the output of this debugging statement. 
     */
    DEBUGMSGTL(("nstAgentSubagentObject",
                "Initializing the nstAgentSubagentObject module
"
)); /* * the line below registers our variables defined above as * accessible and makes it writable. A read only version of any * of these registration would merely call * register_read_only_long_instance() instead. The functions * called below should be consistent with your MIB, however. * * 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. */ DEBUGMSGTL(("nstAgentSubagentObject", "Initalizing nstAgentSubagentObject scalar integer. Default value = %d
"
, nstAgentSubagentObject)); netsnmp_register_long_instance("nstAgentSubagentObject", nstAgentSubagentObject_oid, OID_LENGTH(nstAgentSubagentObject_oid), &nstAgentSubagentObject, NULL); DEBUGMSGTL(("nstAgentSubagentObject", "Done initalizing nstAgentSubagentObject module
"
)); }

nstAgentSubagentObject.hファイル
/*
 * Note: this file originally auto-generated by mib2c using
 *        : mib2c.int_watch.conf,v 5.0 2002/04/20 07:30:13 hardaker Exp $
 */
#ifndef NSTAGENTSUBAGENTOBJECT_H
#define NSTAGENTSUBAGENTOBJECT_H

/*
 * function declarations 
 */
void            init_nstAgentSubagentObject(void);

#endif                          /* NSTAGENTSUBAGENTOBJECT_H */
net-snmp-config --compile-subagent mysubagent nstAgentSubagentObject.c

If all goes well, this should have produced a mysubagent binary file (like the script output above chose).
3.4テスト
#          
snmpd -f -Lo -C --rwcommunity=public --master=agentx --agentXSocket=tcp:localhost:1705 udp:1161

snmpget -v 2c -c public localhost NET-SNMP-TUTORIAL-MIB::nstAgentSubagentObject.0

# NET-SNMP-TUTORIAL-MIB::nstAgentSubagentObject.0 = No Such Object available on this agent at this OID

 ./mysubagent -f -Lo -x  tcp:localhost:1705
 #      
 ./mysubagent 

 snmpget -v 2c -c public localhost NET-SNMP-TUTORIAL-MIB::nstAgentSubagentObject.0
 # NET-SNMP-TUTORIAL-MIB::nstAgentSubagentObject.0 = INTEGER: 2

四、プロジェクト応用
私たちはnet-snmp-config-compile-subagent Test Testを再実行します.c、それからすぐにCtrl+c、時間はコントロールして、net-snmp-configプログラムに臨時のCファイルを生んで、それを削除しませんでした.一時ファイルを開いて、コードを見てみましょう.200行以上です.本文はmain関数の重要な部分だけを貼って、コードに注釈を追加しています.理解しにくいです.

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
", 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:
"
); 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後のTestを修正します.cファイルは以下の通りです.
/* 
 * Note: this file originally auto-generated by mib2c using 
 *        $ 
 */  

#include   
#include   
#include   
#include "Test.h"  
#include   

/** Initializes the Test module */  
void  
init_Test(void)  
{  
    const oid       GetTime_oid[] = { 1, 3, 6, 1, 4, 1, 16535, 1, 1 };  

    DEBUGMSGTL(("Test", "Initializing
"
)); 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
"
, reqinfo->mode); return SNMP_ERR_GENERR; } return SNMP_ERR_NOERROR; } static int keep_running; RETSIGTYPE stop_server(int __attribute__((unused)) a) { keep_running = 0; } int main() { const char *app_name = "Test"; /* we are a subagent */ netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1); /* 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"); keep_running = 1; while(keep_running) { agent_check_and_process(1);/* block every 1 second */ } /* at shutdown time */ snmp_shutdown(app_name); /* deinitialize your mib code here */ /* shutdown the agent library */ shutdown_agent(); return 0; }

snmpd stopの場合stop_が呼び出されますserver、私たちのサブエージェントもログアウトします.
コンパイルして、自分のプロジェクトに参加するので、Makefileに書き込むことをお勧めします.本稿ではMakefileを書かずに、gccコマンド生成(net-snmp-configのパラメータで直接)を呼び出し、snmpdを起動してTestプログラムを実行します.プログラムはブロックされます.デーモンプロセスではありません.mainにはループがあります.以下のようにします.
[root@bogon~]# ./Test   

NET-SNMP version 5.7.2 AgentX subagent connected

結果をテストするためにsnmpgetを呼び出します.
[root@bogon ~]# 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 02:39:17 2013  
"  

リファレンス接続
カスタムMIB拡張:http://blog.csdn.net/hepeng597/article/details/8782868サブエージェントの公式参照:http://www.net-snmp.org/wiki/index.php/TUT:Writing_a_Subagent