EN JA
BSNMPAGENT(3)
BSNMPAGENT(3) FreeBSD Library Functions Manual BSNMPAGENT(3)

名称

bsnmpagent, snmp_depop_t, snmp_op_t, tree, tree_size, snmp_trace, snmp_debug, snmp_get, snmp_getnext, snmp_getbulk, snmp_set, snmp_make_errresp, snmp_dep_lookup, snmp_init_context, snmp_dep_commit, snmp_dep_rollback, snmp_dep_finishSNMP エージェントライブラリ

ライブラリ

Begemot SNMP ライブラリ (libbsnmp, -lbsnmp)

書式

#include < asn1.h>
#include < snmp.h>
#include < snmpagent.h>

typedef int
(*snmp_depop_t)( struct snmp_context *ctx, struct snmp_dependency *dep, enum snmp_depop op);

typedef int
(*snmp_op_t)( struct snmp_context *ctx, struct snmp_value *val, u_int len, u_int idx, enum snmp_op op);

extern struct snmp_node *tree;
extern u_int tree_size;
extern u_int snmp_trace;
extern void (*snmp_debug)(const char *fmt, ...);

enum snmp_ret
snmp_get( struct snmp_pdu *pdu, struct asn_buf *resp_b, struct snmp_pdu *resp, void *data);

enum snmp_ret
snmp_getnext( struct snmp_pdu *pdu, struct asn_buf *resp_b, struct snmp_pdu *resp, void *data);

enum snmp_ret
snmp_getbulk( struct snmp_pdu *pdu, struct asn_buf *resp_b, struct snmp_pdu *resp, void *data);

enum snmp_ret
snmp_set( struct snmp_pdu *pdu, struct asn_buf *resp_b, struct snmp_pdu *resp, void *data);

enum snmp_ret
snmp_make_errresp( const struct snmp_pdu *pdu, struct asn_buf *req_b, struct asn_buf *resp_b);

struct snmp_dependency *
snmp_dep_lookup( struct snmp_context *ctx, const struct asn_oid *base, const struct asn_oid *idx, size_t alloc, snmp_depop_t func);

struct snmp_context *
snmp_init_context( void);

int
snmp_dep_commit( struct snmp_context *ctx);

int
snmp_dep_rollback( struct snmp_context *ctx);

void
snmp_dep_finish( struct snmp_context *ctx);

解説

SNMP ライブラリは SNMP バージョン 1 か 2 を使用する SNMP エージェントアプリケーションを容易に構築するためのルーチンを含んでいます。しかしながら、新しい MIB を取り扱う ( snmpmod(3) 参照) bsnmpd(1) ロード可能なモジュールを構築することはがさらに簡単であることに注意してください、

エージェントルーチンの大部分はエージェントによってサービスされる完全な MIB を説明するグローバルな配列で操作します。この配列は次の 2 つの変数で保持されています:

extern struct snmp_node *tree; 
extern u_int  tree_size;

配列の要素はタイプ struct snmp_node です:

typedef int (*snmp_op_t)(struct snmp_context *, struct snmp_value *, 
    u_int, u_int, enum snmp_op); 
 
struct snmp_node { 
 struct asn_oid oid; 
 const char *name;  /* リーフ (葉) の名前 */ 
 enum snmp_node_type type; /* このノードのタイプ */ 
 enum snmp_syntax syntax; 
 snmp_op_t op; 
 u_int  flags; 
 u_int32_t index;  /* インデックスデータ */ 
 void  *data;  /* アプリケーションデータ */ 
 void  *tree_data; /* アプリケーションデータ */ 
};

この構造体のフィールドは以下に説明されています。

oid
スカラかテーブルカラムのベース OID。
name
この変数の名前。
type
この変数のタイプ。次の 1 つです:

enum snmp_node_type { 
 SNMP_NODE_LEAF = 1, 
 SNMP_NODE_COLUMN 
};
syntax
この変数の SNMP 構文。
op
この変数のためのユーザ供給ハンドラ。ハンドラは次の引数で呼び出されます:
ctx
コンテキスト (下記参照) へのポインタ。 NULL
val
設定されるか、または検索される値。 GETNEXT と GETBULK 操作のために、この値における oid は現在の OID です。 (この場合、テーブル列だけのために呼び出される) 関数は、同じカラムで辞書的に次に存在する OID を見つけて、それに従って、oid と値のサブフィールドを設定しなければなりません。テーブルカラムが使い果たされるなら、関数は SNMP_ERR_NOSUCHNAME を返さなければなりません。他のすべての操作のために、 val の oid は取って来るか設定するための oid です。
len
インデックスのないベース oid の長さ。
idx
テーブルカラムに関しては、これはノードからのインデックス式 (下記参照) です。
op
これ、次の 1 つの実行する操作です:

enum snmp_op { 
 SNMP_OP_GET  = 1, 
 SNMP_OP_GETNEXT, 
 SNMP_OP_SET, 
 SNMP_OP_COMMIT, 
 SNMP_OP_ROLLBACK, 
};

ユーザハンドラは適切な SNMP v2 エラーコードを返さなければなりません。オリジナルの PDU がバージョン 1 PDU であったなら、エラーコードは自動的にマップされます。

flags
現在、ノードのためにだけにフラグ SNMP_NODE_CANSET が定義されて、設定されており、それを書き込むか、または作成することができます。
index
この単語はテーブルカラムのためのインデックスについて記述します。インデックスの各部分はビット 4 で始まる 4 ビット取ります。ビット 0 から 3 はインデックス部分の数を保持します。この整列は最大 7 つのインデックスがあるテーブルを許します。それぞれのビットグループはインデックス部分のための構文を含みます。このフィールドを解析するのを手助けする多くのマクロがあります:

#define SNMP_INDEXES_MAX 7 
#define SNMP_INDEX_SHIFT 4 
#define SNMP_INDEX_MASK 0xf 
#define SNMP_INDEX_COUNT(V) ((V) & SNMP_INDEX_MASK) 
#define SNMP_INDEX(V,I) \ 
 (((V) >> (((I) + 1) * SNMP_INDEX_SHIFT)) &\ 
 SNMP_INDEX_MASK)
data
このフィールドは、任意のデータを含むことができ、ライブラリによって使用されません。

ノードテーブルを構築する最も簡単な方法は gensnmptree(1) です。 SET 操作を実行している間にツリーを変更するとき、慎重でなければならないことに注意してください。 bsnmpd(1) のためにソースを参照してください。

snmp_debug によって指される関数と共にグローバル変数 snmp_trace はライブラリとエージェントをデバッグするのに役に立ちます。 snmp_trace は次のビットがあるビットマスクです:

enum { 
 SNMP_TRACE_GET, 
 SNMP_TRACE_GETNEXT, 
 SNMP_TRACE_SET, 
 SNMP_TRACE_DEPEND, 
 SNMP_TRACE_FIND, 
};

デバッグ文字列の戦略的な位置で snmp_debug() を呼び出すためのライブラリの本当の原因のためのビットを設定します。ライブラリは標準エラーにメッセージを印刷 (表示) するデバッグ関数のためのデフォルトの実装を含んでいます。

関数の多くはいわゆるコンテキストを使用します:

struct snmp_context { 
 u_int var_index; 
 struct snmp_scratch *scratch; 
 struct snmp_dependency *dep; 
 void *data;  /* ユーザデータ */ 
 enum snmp_ret code; /* リターンコード */ 
}; 
 
struct snmp_scratch { 
 void  *ptr1; 
 void  *ptr2; 
 uint32_t int1; 
 uint32_t int2; 
};

フィールドは次のように使用されます:

va_index
ノード操作コールバックのために、これはエラーが発生する場合に返されるべきである変数バインディングのインデックスです。ライブラリによって設定します。他のすべての関数では、これは未定義です。
scratch
ノード操作コールバックのために、これはコミットとロールバックを実装するために使用することができる変数バインディングスクラッチ領域毎へのポインタです。ライブラリによって設定します。
dep
従属関係コールバック関数 (下記参照) では、これは現在の従属関係へのポインタです。ライブラリによって設定します。
data
これは、ライブラリへの呼び出しからの data 引数であり、ライブラリによって使用されません。

次の 3 つの関数は異なった種類の GET 要求を実行します。関数 snmp_get() は、SNMP GET 操作を実行し、関数 snmp_getnext() は、SNMP GETNEXT 操作を実行し、そして、関数 snmp_getbulk() は、SNMP GETBULK 操作を実行します。すべての 3 つの関数において、応答 PDU は急いで構築され、エンコードされます。あらゆるものがうまくいっているなら、応答 PDU は respresp_b に返されます。この場合、呼び出し側は応答 PDU を解放するために snmp_pdu_free() を呼び出さなければなりません。次の値の 1 つが返されます:

SNMP_RET_OK
操作は、成功して、応答 PDU が送信されるかもしれません。
SNMP_RET_IGN
操作は、失敗して、応答 PDU が構築されません。要求は、無視されます。
SNMP_RET_ERR
操作中のエラー。エラーコードとインデックスは pdu に設定されます。応答 PDU は構築されませんでした。呼び出し側は snmp_make_errresp() によってエラー応答を構築するかもしれません。

関数 snmp_set() は、SNMP SET 操作を実行します。引数は前の 3 つの関数と同じです。しかしながら、この関数の操作ははるかに複雑です。

SET 操作はいくつかの段階で起こります:

  1. 各バインドでは対応するノードを検索し、変数が書き込み可能で、構文が間違いないかをチェックします。書き込み可能チェックはスカラのためだけに行うことができます。カラムに関しては、ノードの操作コールバック関数でそれをしなければなりません。
  2. 各バインドでは、ノードの操作コールバックを関数 SNMP_OP_SET で呼び出します。コールバックは従属関係 (dependency) か終了化子 (finalizer) を作成するかもしれません (下記参照)。簡単なスカラのスクラッチ領域は、必要な相互依存テーブルカラムの依存のために、コミットとロールバック (巻き返し) を操作するために十分であるかもしれません。
  3. 前のステップがある点で失敗するなら、ノードの操作コールバック関数は SNMP_OP_SET が反対の順序で SNMP_OP_ROLLBACK で実行されるすべてのバインドのために呼び出されます。これで、すべての変数が SET 操作の効果を元に戻すことができます。この後、すべての従属関係が解放され、終了化子 (finalizer) は 1 の失敗フラグで実行されます。そして、関数は適切なエラー表示で呼び出し側に返ります。
  4. SET ステップがすべてのバインドを成功したなら、従属関係コールバックは従属関係存が SNMP_DEPOP_COMMIT の操作で作成された順序で実行されます。従属関係のいずれかが失敗するなら、すべてのコミットされた従属関係は再び SNMP_DEPOP_ROLLBACK との反対の順序で呼び出されます。すべてのバインドにおいて最後から最初に行われるより、ノードの操作コールバックは SNMP_OP_SET の効果を元に戻すために SNMP_OP_ROLLBACK で呼び出されます。終わりに、従属関係は解放され、終了化子 (finalizer) は 1 の失敗フラグで呼び出され、関数はは適切なエラー表示で呼び出し側に返ります。
  5. 従属関係のコミットが成功するなら、各バインドにおいて、ノードの操作コールバックは SNMP_OP_COMMIT で呼び出されます。コールバックから返されたどんなエラーも無視されます (エラーメッセージは snmp_error() を通して生成されます。)
  6. 現在、従属関係は解放され、終了化子 (finalizer) は 0 の失敗フラグで呼び出されます。それを解放するすぐ前の各従属関係において、そのコールバックは SNMP_DEPOP_FINISH で呼び出されます。そして、関数は SNMP_ERR_OK を返します。

複雑な SET 操作で役に立つメカニズムがあります: 従属関係と終了化子です。いくつかのバインドが互いに依存しているなら、従属関係は使用されます。典型的な例は、後に続くいくつかのカラムの設定を必要とする、概念的な列の作成です。従属関係は 2 つの OID によって識別されます。テーブル場合では、最初の oid は通常はテーブルベース OID であり、2 番目のものは、インデックスです。これらの両方は asn_slice_oid() と共に変数 OID から容易に生成することができます。関数 snmp_dep_lookup() は、これらの 2 つの OID に基づく従属関係を見つけようとします、そして、見つけることができないなら、新しいものを作成します。これは、関数が同じテーブルの列のそれぞれのカラムのために同じ従属関係を返す、テーブルの例を意味します。 SNMP_OP_SET 処理の間に、従属関係への列に関するすべての情報を集めることができます。 snmp_dep_lookup() の引数は次の通りです: 従属関係を識別する 2 つの OID (それら新たに作成された従属関係にコピーされる)、割り付ける構造体のサイズ、および従属関係コールバック。

すべての SNMP_OP_SET 操作が成功したとき、従属関係は実行されます。現在のところ、従属関係コールバックは、この SET PDU で利用可能であった与えられたテーブル列に関するすべての情報があり、それに従って、動作することができます。

それぞれの従属関係コールバックは最小でも一度 SNMP_OP_ROLLBACK の操作で実行されることが保証されます。これは、コールバックにおけるすべての動的に割り付けられたリソースを正しく解放できることを確実にします。

関数 snmp_make_errresp() は、操作が失敗したならエラー応答を行います。それはオリジナルの要求 PDU (それはエラーコードとインデックスフィールドだけを見る)、オリジナルの PDU を含んでいるバッファ、およびエラー PDU のためのバッファを取ります。それは、オリジナルの PDU バッファから直接、応答 PDU までバインドフィールドをコピーして、その結果、このフィールドのデコード可能性に依存しません。それは操作関数と同じ値を返すかもしれません。

次の 4 つの関数は、SET 操作のいくつかの部品が実行されることを可能にします。これは、単一トランザクションとして設定を実装するために bsnmpd(1) で使用されるだけです。関数 snmp_init_context() は、コンテキストを作成して、初期化します。関数 snmp_dep_commit() は、最初のエラーで止まるコンテキストのすべての従属関係のために SNMP_DEPOP_COMMIT を実行します。関数 snmp_dep_rollback() は、コンテキストにおける現在の従属関係の前で始まる SNMP_DEPOP_ROLLBACK を実行します。関数 snmp_dep_finish() は、すべての従属関係のために SNMP_DEPOP_FINISH を実行します。

診断

エラーが関数のいずれかで発生するなら、上記で説明されるエラー指示を返します。さらに、関数は予期せぬエラーで snmp_error を呼び出すかもしれません。

規格

この実現は適切な IETF RFC と ITU-T 勧告に適合しています。

作者

Hartmut Brandt <harti@FreeBSD.org>
October 4, 2005 FreeBSD