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

名称

snmp_client, snmp_send_cb_f, snmp_timeout_cb_f, snmp_timeout_start_f, snmp_timeout_stop_f, snmp_open, snmp_close, snmp_pdu_create, snmp_add_binding, snmp_pdu_check, snmp_pdu_send, snmp_oid_append, snmp_parse_server, snmp_receive, snmp_table_cb_f, snmp_table_fetch, snmp_table_fetch_async, snmp_dialog, snmp_discover_engineSNMP クライアントライブラリ

ライブラリ

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

書式

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

typedef void
(*snmp_send_cb_f)( struct snmp_pdu *req, struct snmp_pdu *resp, void *uarg);

typedef void
(*snmp_timeout_cb_f)( void *uarg);

typedef void *
(*snmp_timeout_start_f)( struct timeval *timeout, snmp_timeout_cb_f callback, void *uarg);

typedef void
(*snmp_timeout_stop_f)( void *timeout_id);

extern struct snmp_client snmp_client;

void
snmp_client_init( struct snmp_client *client);

int
snmp_client_set_host( struct snmp_client *client, const char *host);

int
snmp_client_set_port( struct snmp_client *client, const char *port);

int
snmp_open( const char *host, const char *port, const char *read_community, const char *write_community);

void
snmp_close( void);

void
snmp_pdu_create( struct snmp_pdu *pdu, u_int op);

int
snmp_add_binding( struct snmp_pdu *pdu, ...);

int
snmp_pdu_check( const struct snmp_pdu *req, const struct snmp_pdu *resp);

int32_t
snmp_pdu_send( struct snmp_pdu *pdu, snmp_send_cb_f func, void *uarg);

int
snmp_oid_append( struct asn_oid *oid, const char *fmt, ...);

int
snmp_parse_server( struct snmp_client *sc, const char *str);

int
snmp_receive( int blocking);

typedef void
(*snmp_table_cb_f)( void *list, void *arg, int res);

int
snmp_table_fetch( const struct snmp_table *descr, void *list);

int
snmp_table_fetch_async( const struct snmp_table *descr, void *list, snmp_table_cb_f callback, void *uarg);

int
snmp_dialog( struct snmp_pdu *req, struct snmp_pdu *resp);

int
snmp_discover_engine( void);

解説

SNMP ライブラリは、SNMP バージョン 1、2 または 3 を使用する SNMP クライアントアプリケーションを容易に構築するルーチンを含んでいます。ルーチンの大部分は、 struct snmp_client を使用します:

struct snmp_client { 
 enum snmp_version version; 
 int   trans; /* 使用する転送タイプ */ 
 
 /* これらの 2 つは, アプリケーションでは読み込み専用です */ 
 char   *cport; /* 文字列のポート番号*/ 
 char   *chost; /* 文字列のホスト名と IP アドレス */ 
 
 char   read_community[SNMP_COMMUNITY_MAXLEN + 1]; 
 char   write_community[SNMP_COMMUNITY_MAXLEN + 1]; 
 
 /* SNMPv3 特有のフィールド */ 
 int32_t   identifier; 
 int32_t   security_model; 
 struct snmp_engine engine; 
 struct snmp_user user; 
 
 /* SNMPv3 Access 制御 - VACM*/ 
 uint32_t  clen; 
 uint8_t   cengine[SNMP_ENGINE_ID_SIZ]; 
 char   cname[SNMP_CONTEXT_NAME_SIZ]; 
 
 struct timeval  timeout; 
 u_int   retries; 
 
 int   dump_pdus; 
 
 size_t   txbuflen; 
 size_t   rxbuflen; 
 
 int   fd; 
 
 int32_t   next_reqid; 
 int32_t   max_reqid; 
 int32_t   min_reqid; 
 
 char   error[SNMP_STRERROR_LEN]; 
 
 snmp_timeout_start_f timeout_start; 
 snmp_timeout_stop_f timeout_stop; 
 
 char   local_path[sizeof(SNMP_LOCAL_PATH)]; 
};

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

version
これは使用する SNMP のバージョンです。適切な値に関しては bsnmplib(3) を参照してください。デフォルトバージョンは SNMP_V2c です。
trans
これが SNMP_TRANS_LOC_DGRAM であるなら、ローカルデータグラムソケットが使用されます。それが SNMP_TRANS_LOC_STREAM であるなら、ローカルストリームソケットが使用されます。 SNMP_TRANS_UDP に関しては、UDP ソケットが作成されます。それはローカルソケットのためのサーバのソケットへのパスとして chost フィールドを使用します。
cport
SNMP エージェントの UDP ポート番号。これはシンボリックな ( /etc/services からの) ポート番号、または、数値のポート番号であるかもしれません。このフィールドが NULL (デフォルト) であるなら、標準の SNMP ポートが使用されます。このフィールドは直接変更するべきではなく、 snmp_client_set_port() の呼び出しによって変更するべきです。
chost
SNMP エージェントのホスト名、IP アドレスまたは UNIX ドメインソケットパス名。これが NULL (デフォルト) であるなら、 localhost が仮定されます。このフィールドは直接変更するべきではなく、 snmp_client_set_host() の呼び出しによって変更するべきです。
read_community
これは SET 要求以外のすべての要求に使用されるコミュニティ名です。デフォルトは‘public’です。
write_community
SET 要求に使用されるコミュニティ名。デフォルトは‘private’です。
identifier
SNMPv3 PDU で使用されるメッセージ識別子の値。各転送 PDU で増加されます。
security_model
SNMPv3 PDU で使用されるセキュリティモデル。現在の、RFC 3414 (値 3) によって指定された User-Based Security モデルだけが、サポートされます。
engine
SNMPv3 PDU で使用される信頼すべき SNMP エンジンのパラメータ。
user
SNMPv3 PDU で使用される USM SNMP ユーザ資格証明。
clen
SNMPv3 PDU で使用されるコンテキストエンジン ID の長さ。
cengine
SNMPv3 PDU で使用されるコンテキストエンジン ID。デフォルトは、空です。
cname
SNMPv3 PDU で使用されるコンテキスト名。デフォルトは、‘’です。
timeout
要求の応答を待つ最大の時間。時間が経過するなら、要求は retries 回まで再送信されます。デフォルトは 3 秒です。
retries
要求 PDU が再送信される回数。 0 に設定するなら、一度だけ要求を送信します。デフォルトは 3 再送信です。
dump_pdus
0 以外の値に設定されるなら、すべての受信と送信 PDU は snmp_pdu_dump(3) を通してダンプされます。デフォルトは PDU をダンプしません。
txbuflen
転送された PDU のために割り付けられるエンコード用のバッファサイズ。デフォルトは 10000 オクテットです。
rxbuflen
受信 PDU のために割り付けられるデコード用のバッファサイズ。これは受信することができる最大の PDU のサイズです。デフォルトは 10000 オクテットです。
fd
snmp_open() を呼び出した後で、送信と受信 PDU に使用されるファイルソケットファイル記述子です。
next_reqid
送信される次の PDU の要求 ID。ライブラリによって内部で使用されます。
max_reqid
発信 PDU に使用する最大の要求 ID。デフォルトは INT32_MAX です。
min_reqid
発信 PDU に使用する最小の要求 ID。要求 ID は min_reqid で始まり max_reqid まで直線的に割り付けられます。
error
エラーが起こるなら、このフィールドはエラーついて説明する印刷可能な文字列に設定されます。
timeout_start
このフィールドは 1 回限りのタイムアウトを設定する関数を指さなければなりません。タイムアウトが経過した後に、与えられたコールバック関数はユーザ引数で呼び出されなければなりません。 timeout_start() 関数はタイムアウトを識別する void * を返さなければなりません。
timeout_stop
このフィールドは実行タイムアウトを停止する関数に設定されければなりません。関数は対応する timeout_start() 関数の返り値で呼び出されます。
local_path
ローカルソケットモードではクライアントソケットの名前。アプリケーションでは、必要ありません。

現在の実装ではすべてのライブラリ関数によって使用されるグローバル変数

extern struct snmp_client snmp_client;

があります。ライブラリへの最初の呼び出しはこのグローバル変数をデフォルト値に初期化するために snmp_client_init() への呼び出しでなければなりません。この呼び出しの後で snmp_open() の呼び出しの前に、変数のフィールドはユーザによって変更されてもよいです。 chostcport フィールドの変更は、関数 snmp_client_set_host() と snmp_client_set_port() を通してのみ行われるべきです。

関数 snmp_open() は UDP または UNIX ドメインソケットを作成して、それをエージェントの IP アドレスとポートに接続します。呼び出しの引数のいずれが NULL でないなら、グローバル snmp_client の対応するフィールドは引数から設定されます。そうでなければ、その変数に既にある値が使用されます。関数 snmp_close() はソケットをクローズして、すべてのタイムアウトを停止し、すべての動的にに割り付けられたリソースを解放します。

次の 3 つの関数が、要求 PDU を作成するために使用されます。関数 snmp_pdu_create() はタイプ op の PDU を初期化します。それは PDU 自体のための空間を割り付けません。これは呼び出し側の責任です。 snmp_add_binding() は PDU へのバインドを加えて、最初の新しいバインドの (0 を底とする) インデックスを返します。引数は NULL で終了する OID と構文定数へのポインタの組です。呼び出し

snmp_add_binding(&pdu, 
    &oid1, SNMP_SYNTAX_INTEGER, 
    &oid2, SNMP_SYNTAX_OCTETSTRING, 
    NULL);

は PDU に 2 つの新しいバインドを加えて、最初のバインドのインデックスを返します。必要であるなら、バインドの値部分を設定するのは、呼び出し側の責任です。関数はバインドの最大数が使い果たされるなら、-1 を返します。関数 snmp_oid_append() は要求のために変数 OID を構築するために使用することができます。それは構築される struct asn_oid へのポインタ、書式文字列、と書式文字列に依存するタイプの多くの引数を取ります。書式文字列は次の方法で文字ごとに解釈されます:

i
この書式は、タイプ asn_subid_t の引数を期待し、一つの整数としてこれを OID に追加します。
a
この書式は、タイプ struct in_addr の引数を期待し、OID への IP アドレスの 4 つの部分に追加します。
s
この書式は、タイプ const char * の引数を期待し、 ( strlen(3) で計算される) 文字列の長さと文字列中のそれぞれの文字を OID に追加します。
(
N)
この書式は、引数を期待しません。 N は、10 進数でなければならなく、内部の変数 size に格納されます。
b
この書式は、タイプ const char * の引数を期待し、文字列から size 文字を OID に追加します。文字列は NUL (ヌル文字) を含むかもしれません。
c
この書式は 2 つの引数を期待します: 1 つはタイプ size_t と、1 つはタイプ const u_char * です。最初の引数は 2 番目の引数によって指された文字列から OID に追加するバイト数を与えます。

関数 snmp_pdu_check() は、応答 PDU をチェックするために使用されます。多くのチェックが実行されます (エラーコード、バインドの等しい数、構文、と SET PDU の値)。関数は、すべてがうまくいくなら、+1 を返し、 NOSUCHNAME か同様のエラーが検出されたなら、0 を返し、応答 PDU で致命的なエラーがあれば、-1 を返し、 respNULL (タイムアウトが起こった) ならば、-2 を返します。

関数 snmp_pdu_send() は与えられた PDU をエンコードして、送信します。内部リスト中のコールバックとユーザポインタと共に PDU を記録して、応答が受信されないなら、再転送をを準備します。応答が受信されているか、または再転送カウントが越えているとき、コールバック func はオリジナルの要求 PDU、応答 PDU、とユーザ引数 uarg で呼び出されます。再転送カウントが超えているなら、 func はオリジナルの要求 PDU、 NULL に設定された応答ポインタ、とユーザ引数 uarg で呼び出されます。議論 uarg に設定された応答ポインタで呼び出されます。呼び出し側はコールバック関数が呼び出されれるまで、要求 PDU を解放するべきではありません。コールバック関数は、要求 PDU と応答 PDU ( NULL でなければ) を解放しなければなりません。

関数 snmp_receive() は PDU を受信する試みをします。引数が 0 なら、関数はパケットが利用可能であるかどうか調べるためにポーリングし、引数が 0 でないなら、関数は次のパケットが受信されるまでブロックします。パケットは普通のコールバックメカニズム (応答でないパケットは静かに落とされます) によって配信されます。関数は、パケットが受信され、ディスパッチが成功すれば、0 を返し、エラーが起こるか、(ポーリングモードで) パケットが利用可能でないなら、-1 を返します。

次の 2 つの関数は、SNMP エージェントからテーブルを検索するために使用されます。それらは、テーブルについて説明する、次の入力構造体を使用します:

struct snmp_table { 
 struct asn_oid  table; 
 struct asn_oid  last_change; 
 u_int   max_iter; 
 size_t   entry_size; 
 u_int   index_size; 
 uint64_t  req_mask; 
 
 struct snmp_table_entry { 
     asn_subid_t  subid; 
     enum snmp_syntax syntax; 
     off_t  offset; 
 }   entries[]; 
};

この構造体のフィールドには、次の意味があります:

table
これはテーブルのベース OID です。
last_change
いくつかのテーブルはそれらにアタッチする、タイプ TIMETICKS のスカラ変数があり、それはテーブルが最後に変更された時間を保持しています。この OID はこの変数 (.0 インデックスなし) の OID であるべきです。テーブルが複数の GET 要求で検索され、2 の要求の間で変数が変更されるとき、テーブルフェッチは再開されます。
max_iter
テーブルをフェッチする試みの最大数。
entry_size
テーブルフェッチルーチンはそれぞれのテーブルの列のために構造体のリストを返します。この変数は、1 つの構造体のサイズであり、構造体を malloc(3) する (割り付ける) ために使用されます。
index_size
これはテーブルのインデックスカラムの数です。
req_mask
これは必要とされる各テーブルカラムののための 1 のビットマスクです。ビット 0 は配列 entries の最初の要素 (インデックス 0)、ビット 1 は 2 番目 (インデックス 1)、などに対応しています。 SNMP テーブルはスパーズ (まばら) であるかもしれません。スパースカラムにおいて、ビットを設定するべきではありません。与えられたカラムのためのビットを設定して、カラム値で与えられた列を検索することができないなら、テーブルが現在エージェントによって変更されていると仮定して、テーブルフェッチは再開されます。インデックスカラムのためのビットは無視されます。
entries
これはカラム記述子の可変サイズの配列です。この配列は、構文 SNMP_SYNTAX_NULL の要素で終了します。最初の index_size 要素はテーブルに関するすべてのインデックスカラムについて記述し、残りは標準のカラムです。‘ entries[N]’のカラムで式‘ req_mask & (1 << N)’が真となるなら、カラムは要求されたカラムと見なされます。この配列の要素のフィールドは次の意味があります:
subid
これはカラムの OID subid です。これはインデックスエントリで無視されます。インデックスエントリは syntax フィールドに従って、デコードされます。
syntax
これはカラムかインデックスの構文です。 SNMP_SYNTAX_NULL の構文は配列を終了します。
offset
これは返された構造体のカラムの値の始めのオフセットです。このフィールドは ISO-C offsetof() マクロで設定することができます。

両方のテーブルフェッチ関数は、それぞれのテーブルの列あたり 1 つの構造体の TAILQ ( queue(3) 参照) を返します。これらの構造体は TAILQ_ENTRY() と uint64_t で始まらなければならなくて、 malloc(3) によって割り付けられます。テーブル関数の list 引数は TAILQ_HEAD() を指さなければなりません。通常、 found と呼ばれる uint64_t フィールドは、与えられた列が見つけられているカラムを示すために使用されます。それは req_mask フィールドのようにエンコードされます。

関数 snmp_table_fetch() は与えられたテーブルを同期的にフェッチします。すべてがうまくいったなら、0 を返します。そうでなければ、関数は、適切なエラー文字列を設定して -1 を返します。関数 snmp_table_fetch_async() はテーブルを非同期的にフェッチします。全体のテーブルがフェッチされるか、またはエラーが起こったなら、コールバック関数 callback は呼び出し側の引数 listuarg で呼び出され、パラメータはテーブルがフェッチされたなら、0、エラーが起こったなら -1 のいずれかです。関数自体は、テーブルのフェッチを初期化することができないなら、-1 を返します。

次のテーブル記述は ATM インタフェーステーブルをフェッチするために使用されます:

/* 
 * ATM インタフェーステーブル 
 */ 
struct atmif { 
 TAILQ_ENTRY(atmif) link; 
 uint64_t found; 
 int32_t  index; 
 u_char  *ifname; 
 size_t  ifnamelen; 
 uint32_t node_id; 
 uint32_t pcr; 
 int32_t  media; 
 uint32_t vpi_bits; 
 uint32_t vci_bits; 
 uint32_t max_vpcs; 
 uint32_t max_vccs; 
 u_char  *esi; 
 size_t  esilen; 
 int32_t  carrier; 
}; 
TAILQ_HEAD(atmif_list, atmif); 
 
/* すべての ATM インタフェースのリスト */ 
struct atmif_list atmif_list; 
 
static const struct snmp_table atmif_table = { 
 OIDX_begemotAtmIfTable, 
 OIDX_begemotAtmIfTableLastChange, 2, 
 sizeof(struct atmif), 
 1, 0x7ffULL, 
 { 
   { 0, SNMP_SYNTAX_INTEGER, 
  offsetof(struct atmif, index) }, 
   { 1, SNMP_SYNTAX_OCTETSTRING, 
  offsetof(struct atmif, ifname) }, 
   { 2, SNMP_SYNTAX_GAUGE, 
  offsetof(struct atmif, node_id) }, 
   { 3, SNMP_SYNTAX_GAUGE, 
  offsetof(struct atmif, pcr) }, 
   { 4, SNMP_SYNTAX_INTEGER, 
  offsetof(struct atmif, media) }, 
   { 5, SNMP_SYNTAX_GAUGE, 
  offsetof(struct atmif, vpi_bits) }, 
   { 6, SNMP_SYNTAX_GAUGE, 
  offsetof(struct atmif, vci_bits) }, 
   { 7, SNMP_SYNTAX_GAUGE, 
  offsetof(struct atmif, max_vpcs) }, 
   { 8, SNMP_SYNTAX_GAUGE, 
  offsetof(struct atmif, max_vccs) }, 
   { 9, SNMP_SYNTAX_OCTETSTRING, 
  offsetof(struct atmif, esi) }, 
   { 10, SNMP_SYNTAX_INTEGER, 
  offsetof(struct atmif, carrier) }, 
          { 0, SNMP_SYNTAX_NULL, 0 } 
 } 
}; 
 
... 
 if (snmp_table_fetch(&atmif_table, &atmif_list) != 0) 
  errx(1, "AtmIf table: %s", snmp_client.error); 
...

関数 snmp_dialog() は、エージェントで同期ダイアログを実行するために使用されます。要求 PDU req が送信され、関数は応答 PDU が受信されるまでブロックされます。非同期受信 (すなわち、他のコールバック関数は呼び出しを送信するか、またはテーブルフェッチは関数中で呼び出されます)。が取り扱われることに注意してください。応答 PDU は resp 中に返されます。すべてのタイムアウトと再試行の後で応答を受信することができないなら、関数は -1 を返します。応答が受信されたなら、0 を返します。

関数 snmp_discover_engine() は、リモート SNMPv3 エージェントの信頼すべき snmpEngineId を発見するために使用されます。空の USM ユーザ名がある要求 PDU が送信され、クライアントのエンジンのパラメータは、応答 PDU で受信された snmpEngine パラメータに従って設定されます。クライアントが、認証、および、プライバシを使用するために設定され、応答の snmpEngineBoots、および、snmpEngineTime が 0 の値であったなら、適切なユーザ資格証明がある追加要求 (もしかすると暗号化されている) は、失われた値をとって来るために送信されます。関数は、発見プロセスが完了するまで、ブロックされることに注意してください。すべてのタイムアウトと再試行の後に応答が受信されなかったか、または応答がエラーを含んでいたなら、関数は、-1 を返します。発見プロセスが完了しなかったなら、0 が返されます。

関数 snmp_parse_server() は、SNMP サーバ仕様文字列を解析して、 struct snmp_client のフィールドに書き込むために使用されます。サーバ仕様のシンタック (構文) は

[trans::][community@][server][:port]

です、ここで、 trans は転送名です (udp の 1 つで、stream または dgram)、 community は、読み込みと書き込み共同体 (community) の両方で使用される文字列です、 server は、UDP の場合はサーバのホスト名でローカルソケットの場合はパス名です、そして、 port は、UDP 転送の場合のポートです。関数は、成功の場合は 0 を返し、エラーの場合はエラー文字列を設定して、-1 を返します。

診断

エラーが関数のいずれかで発生するなら、上で説明されるエラー表示を返します。さらに、関数は snmp_clienterror フィールドに印刷可能なエラー文字列を設定します。

規格

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

作者

Hartmut Brandt <harti@FreeBSD.org> Kendy Kutzner <kutzner@fokus.gmd.de>
September 9, 2010 FreeBSD