ucd-snmp agent

關於ucd-snmp軟件包   

ucd-snmp介紹

ucd-snmp源自於卡耐基.梅隆大學的SNMP軟件包 CMU snmp 2.1.2.1, 由加州大學Davis分校(University of Califonia at Davis)開發與維護, 所以命名爲ucd-snmp. 2000年11月ucd-snmp項目轉到由SourceForge(www.sourceforge.net)管理, 並更名爲net-snmp. ucd-snmp 4.2 是以ucd-snmp命名的最後的一個主要版本. 也就是說, 以後發佈的 ucd-snmp 4.2.x僅僅修改軟件包中的Bugs; 而大的修改版本將以net-snmp命名, 併發布爲5.x. ucd-snmp 4.2.1是最新的發佈版本, 於2001年4月4日發佈.

ucd-snmp 4.2.1軟件包由如下內容組成:
¨ 一個可擴展的SNMP代理程序(snmpd);
¨ 一個SNMP代理和管理程序開發庫;
¨ 幾個用於請求或設置SNMP代理變量的工具程序(snmpget, snmpset, snmptable, snmpwalk等);
¨ 幾個用於生成或處理SNMP陷阱(trap)的工具程序(snmptrapd和snmptrap);
¨ 一個標準Unix命令netstat的SNMP版本(snmpnetstat);
¨ 一個基於Tk/perl的MIB瀏覽器(tkmib)

ucd-snmp 4.2.1的文檔:
¨ REAME系列
¨ FAQ
¨ INSTALL
¨ PORTING
¨ 關於工具程序, 配置文件, 和API的man手冊
¨ 一份關於如何擴展代理程序的指南(AGENT.txt)
¨ 位於 http://net-snmp.sourceforge.net/tutorial 的一份入門手冊
注 意: 建議的閱讀順序, REAME----->;INSTALL------>;Tutorial. 在嘗試Tutorial中的例程時, 遇到問題, 參見FAQ; 再根據FAQ指引, 參見相應的文檔. (這是我熟悉這個軟件包的過程. :-) ) 另外, 在軟件包中有一個工具程序, FAQ2HTML, 可以將FAQ轉換成HTML格式,便於瀏覽或查找.

ucd-snmp的維護網 址: http://net-snmp.sourceforge.net. 在此網站上可以下載各個版本和各種形式的ucd-snmp軟件包, 還有關於如何使用, 如何擴展開發等的相關文檔. 如何訂閱相關的郵件列表, 可以參見FAQ中的相關內容.

ucd-snmp 4.2.1支持的操作系統(包括應用程序和代理程序, 至少部分支持):
¨ HP-UX (10.20 to 9.01)
¨ Ultrix (4.5 to 4.2)
¨ Solaris (2.8 to 2.3) and SunOS (4.1.4 to 4.1.2)
¨ OSF (4.0, 3.2)
¨ NetBSD (1.5alpha to 1.0)
¨ FreeBSD (4.1 to 2.2)
¨ BSDi (4.0.1 to 2.1)
¨ Linux (kernels 2.2 to 1.3)
¨ AIX (4.1.5, 3.2.5)
¨ OpenBSD (2.8, 2.6)
¨ Irix (6.5 to 5.1)
注意: 某些系統不支持某些功能模塊,具體情況及處理方法,參見FAQ文檔.

ucd-snmp 4.2.1也可以運行於win32平臺, 具體情況參見README.win32文檔.

ucd-snmp 4.2.1 支持如下SNMP協議版本:
¨ SNMPv1 (RFCs 1155-1157)
¨ SNMPv2c (RFCs 1901-1908)
¨ SNMPv3 (RFCs 2271-2275)
瞭解SNMP協議以及不同版本之間的區別, 可以閱讀這些RFC文檔和FAQ. RFC文檔可以從如下網頁檢索並下載, http://www.nexor.com/index-rfc.htm

關於ucd-snmp 4.2.1的安裝, 主要參見INSTALL文檔. 需要注意的是, 必須還安裝SNMP perl擴展模塊. 因爲有些工具程序是perl腳本文件, 需要這個擴展模塊的支持, 如mib2c, snmpconf, FAQ2HTML等. 而tkmib工具需要Tk.pm 模塊支持. 在軟件包中自帶 SNMP perl模塊, 而沒有Tk.pm. 可以到如下網站下載, www.cpan.org (關於這個網站的說明是, 幾乎涵蓋了所有的 perl 模塊). 

一個簡單的SNMP網絡管理程序

下面, 讓我們先應用ucd-snmp 4.2.1寫一個的SNMP網絡程序, 從應用程序的角度嘗試一下這個軟件包的使用. 這個程序是如此地簡單, 不支持任何命令行參數, 僅僅從代理程序獲得關於系統的描述.

程序代碼如下:

1) /* snmpapp.c - a simple SNMP application */

2) #include <ucd-snmp/ucd-snmp-config.h>;
3) #include <ucd-snmp/ucd-snmp-includes.h>;
4) #include <ucd-snmp/system.h>; 

5) int main(int argc, char * argv[])
6) {
7) struct snmp_session session, *ss;
8) struct snmp_pdu *request, *response;
9) 
10) oid myoid[MAX_OID_LEN];
11) size_t myoid_len = MAX_OID_LEN;

12) struct variable_list *vars;
13) int status;

14) init_snmp("snmpapp");

15) snmp_sess_init( &session );
16) session.version = SNMP_VERSION_1; 
17) session.peername = "localhost";
18) session.community = "public";
19) session.community_len = strlen(session.community);

20) SOCK_STARTUP;
21) ss = snmp_open(&session);

22) request = snmp_pdu_create(SNMP_MSG_GET);

23) read_objid("system.sysDescr.0", myoid, &myoid_len);
24) snmp_add_null_var(request, myoid, myoid_len);

25) status = snmp_synch_response(ss, request, &response);

26) if (status == STAT_SUCCESS && 
27) response->;errstat == SNMP_ERR_NOERROR)
28) {
29) for(vars = response->;variables; vars; vars = vars->;next_variable)
30) print_variable(vars->;name, vars->;name_length, vars);
31) } else {
32) if (status == STAT_SUCCESS)
33) fprintf(stderr, "Error in packet\nReason: %s\n",
34) snmp_errstring(response->;errstat));
35) else
36) snmp_sess_perror("snmpget", ss);
37) }

38) if (response)
39) snmp_free_pdu(response);
40) snmp_close(ss);

41) SOCK_CLEANUP;
42) return (0);
43) }
第2-4行, 必須包含的頭文件, 其中<ucd-snmp/system.h>;如果在<ucd-snmp/ucd-snmp-includes.h>;中已包含, 可以省略. 不過, 在頭文件中有宏保護, 所以無所謂.

第7-13行, 定義程序所需要的變量.

第14行, 初始化SNMP庫.

第15-19行, 初始化會話結構變量. 假定SNMP代理位於本機, community(如何翻譯?)名public具有可讀權限.

第20行和第41行, SOCK_STARTUP和SOCK_CLEANUP宏定義主要用於在win32平臺初始化和清除winsock接口, 而在Unix/Linux環境不做任何事情.

第21行, 打開一個snmp會話. 在下面的會話過程中使用API snmp_open()返回的指針. 關於snmp_open(), 參見相應的man手冊.

第22-24行, 創建一個SNMPv1 PDU, 並加入請求代碼. 注意這裏我們使用的是SNMP Get請求.(宏SNMP_MSG_GET表示).

第25行, 與SNMP代理進行通訊. 這裏使用的是同步通訊機制.

第26-37行, 處理反饋. 注意消息及錯誤的處理方式.

第38-39行, 如果通訊成功, 反饋指針response非空, 必須由程序釋放API分配的內存.

第40行, 關閉會話.

ucd-snmp API分爲如下幾類:
¨ snmp_api
¨ snmp_sess_api
¨ mib_api
¨ variables
¨ default_store
¨ read_config
¨ snmp_alarm
¨ snmp_trap_api
¨ anmp_agent_api
上 面程序用到如下API: init_snmp(), snmp_sess_init(), snmp_open(), snmp_pdu_create(), read_objid(), snmp_add_null_var(), print_variable (), snmp_errstring(), snmp_sess_perror(), snmp_pdu_free(), snmp_close().
具體的API語義和語法, 參見相應的man手冊或頭文件.

在Rad Hat Linux 6.2環境中用如下命令編譯該程序:
gcc -g -I/usr/local/include -o snmpapp snmpapp.c -L/usr/local/lib -lsnmp
其中/usr/local爲ucd-snmp 4.2.1的確省安裝目錄. 
編譯通過, 運行程序獲得SNMP代理運行系統的描述. (在當前情況下, 當然是本機Red Hat Linux 6.2系統的描述). 當然, 必須事先在本機運行SNMP代理:
# /usr/local/sbin/snmpd (必須是root用戶)


一個簡單的MIB模塊

接下來, 嘗試擴展ucd-snmp代理程序snmpd的幾種方式.

首先編寫一個需要加入的MIB模塊定義文件. 編寫MIB模塊定義文件的語法, 由SNMP 協議中SMI部分描述. SMI所採用的是ASN.1的一個子集. 具體的描述參見相應的RFC文檔. 由於我現在不是很精通如何定義MIB模塊, 所以下面借用了ucd-snmp項目組的一個MIB示例文件.

MIB模塊定義文件如下:

1) -- UCD-SNMP-TUTORIAL-MIB.txt

2) UCD-SNMP-TUTORIAL-MIB DEFINITIONS ::= BEGIN
3) IMPORTS
4) ucdExperimental FROM UCD-SNMP-MIB,
5) MODULE-IDENTITY FROM SNMPv2-SMI
6) MODULE-COMPLIANCE, OBJECT-GROUP FROM SNMPv2-CONF;

7) ucdSnmpTutorialMIB MODULE-IDENTITY
8) LAST-UPDATED "0005150000Z"
9) ORGANIZATION "UCDavis"
10) CONTACT-INFO "
11) Author: Wes Hardaker
12) University of California at Davis
13) postal: IT-DCAS
14) UCDavis
15) Davis, CA 95616
16) USA
17) email: [email protected]
18) phone: +1-530-754-7571
19) "
20) DESCRIPTION "A simple mib for demonstration purposes.
21) "
22) ::= { ucdExperimental 4242 }

23) ustMIBObjects OBJECT IDENTIFIER ::= { ucdSnmpTutorialMIB 1 }
24) ustMIBConformance OBJECT IDENTIFIER ::= { ucdSnmpTutorialMIB 2 }

25) ustScalarSet OBJECT IDENTIFIER ::= { ustMIBObjects 1 }

26) ustSSSimpleString OBJECT-TYPE
27) SYNTAX OCTET STRING
28) MAX-ACCESS read-write
29) STATUS current
30) DESCRIPTION
31) "This is a simple test string. It does nothing more than
32) return its current value, and changes values only when set by
33) an incoming SNMP set request."
34) DEFVAL { Hello World }
35) ::= { ustScalarSet 1 }

36) ustSSSecondsSinceChanged OBJECT-TYPE
37) SYNTAX TimeTicks
38) UNITS "1/100th Seconds"
39) MAX-ACCESS read-only
40) STATUS current
41) DESCRIPTION
42) "This object indicates the number of 1/100th seconds since the
43) ustSSSimpleString object has changed. If it is has never been
44) modified, it will be the time passed since the start of the
45) agent."
46) ::= { ustScalarSet 2 }

47) END

該MIB定義文件在MIB樹 iso.org.dod.internet.private.enterprise.ucd.ucdExperimental上定義了一個子樹 ucdSnmpTutorialMIB, 包含一個ustScalarSet對象, 該對象包含兩個變量, ustSSSimpleString和ustSSSenconsSinceChanged. 其中ustSSSimpleString爲字符串類型, 可讀寫. ustSSSenconsSinceChanged爲時間類型, 只讀, 記錄ustSSSimpleString變量自上次修改到現在的時間值. 我們的目的是在代理程序中加入這個模塊, 並能通過工具程序獲得或設置變量的值. 首先通過工具mib2c生成C代碼.

mib2c工具

mib2c是ucd- snmp 4.2新加入的由perl語言編寫的工具程序. 該工具程序需要SNMP perl擴展模塊支持. 首先, 將上面的MIB定義文件拷貝到目錄/usr/local/share/snmp/mibs下. 然後, 以如下命令運行mib2c工具:
/usr/local/bin/mib2c ustScalarSet
mib2c在當前目錄下生成兩個文件: ustScalarSet.h 和ustScalarSet.c. 文件如下.
ustScalarSet.h :

1) /* This file was generated by mib2c and is intended for use as a mib module
for the ucd-snmp snmpd agent. */

2) #ifndef _MIBGROUP_USTSCALARSET_H
3) #define _MIBGROUP_USTSCALARSET_H

4) /* we may use header_generic and header_simple_table from the util_funcs module */
5) config_require(util_funcs)

6) /* function prototypes */
7) void init_ustScalarSet(void);
8) FindVarMethod var_ustScalarSet;
9) WriteMethod write_ustSSSimpleString;

10) #endif /* _MIBGROUP_USTSCALARSET_H */

ustScalarSet.c :

1) /* Most of this file was generated by the mib2c perl script. */

2) #ifdef IN_UCD_SNMP_SOURCE
3) /* If we're compiling this file inside the ucd-snmp source tree */
4) /* This should always be included first before anything else */
5) #include <config.h>;

6) /* minimal include directives */
7) #include "mibincl.h"
8) #include "util_funcs.h"

9) #else /* !IN_UCD_SNMP_SOURCE */

10) #include <ucd-snmp/ucd-snmp-config.h>;
11) #include <ucd-snmp/ucd-snmp-includes.h>;
12) #include <ucd-snmp/ucd-snmp-agent-includes.h>;

13) #endif /* !IN_UCD_SNMP_SOURCE */

14) #if HAVE_STRING_H
15) #include <string.h>;
16) #else
17) #include <strings.h>;
18) #endif

19) #include "ustScalarSet.h"

20) /* 
21) ustScalarSet_variables_oid:
22) this is the top level oid that we want to register under. This
23) is essentially a prefix, with the suffix appearing in the
24) variable below.
25) */

26) static oid ustScalarSet_variables_oid[] = 
27) { 1,3,6,1,4,1,2021,13,4242,1,1 };

28) /*
29) Global variables to store data we're interesting in serving:
30) */
31) static char *ustSSSimpleString;
32) static size_t ustSSSimpleString_len;
33) static time_t lastChanged=0;

34) /* 
35) variable2 ustScalarSet_variables:
36) this variable defines function callbacks and type return information 
37) for the ustScalarSet mib section 
38) */

39) struct variable2 ustScalarSet_variables[] = {
40) #define USTSSSIMPLESTRING 1
41) { USTSSSIMPLESTRING , ASN_OCTET_STR , RWRITE, var_ustScalarSet, 1, { 1 } },
42) #define USTSSSECONDSSINCECHANGED 2
43) { USTSSSECONDSSINCECHANGED, ASN_TIMETICKS , RONLY , var_ustScalarSet, 1, { 2 } },

44) };
45) /* (L = length of the oidsuffix) */

46) /* deinit call for supporting dynamic shared object loading/unloading */
47) void deinit_ustScalarSet(void) {
48) DEBUGMSGTL(("ustScalarSet","unloading\n"));
49) unregister_mib(ustScalarSet_variables_oid,
50) sizeof(ustScalarSet_variables_oid)/sizeof(oid));
51) }

52) /*
53) init_ustScalarSet():
54) Initialization routine. This is called when the agent starts up.
55) At a minimum, registration of your variables should take place here.
56) */
57) void init_ustScalarSet(void) {
58) DEBUGMSGTL(("ustScalarSet","initializing\n"));

59) /* register ourselves with the agent to handle our mib tree */
60) REGISTER_MIB("ustScalarSet", ustScalarSet_variables, variable2,
61) ustScalarSet_variables_oid);

62) /* place any other initialization junk you need here */
63) ustSSSimpleString = strdup("Hello World");
64) ustSSSimpleString_len = strlen(ustSSSimpleString);
65) lastChanged = time(NULL);
66) }

67) /*
68) var_ustScalarSet():
69) This function is called every time the agent gets a request for
70) a scalar variable that might be found within your mib section
71) registered above. It is up to you to do the right thing and
72) return the correct value.
73) You should also correct the value of "var_len" if necessary.
74) *
75) Please see the documentation for more information about writing
76) module extensions, and check out the examples in the examples
77) and mibII directories.
78) */
79) unsigned char *
80) var_ustScalarSet(struct variable *vp, 
81) oid *name, 
82) size_t *length, 
83) int exact, 
84) size_t *var_len, 
85) WriteMethod **write_method)
86) {
87) /* variables we may use later */
88) static long long_ret;

89) if (header_generic(vp,name,length,exact,var_len,write_method)
90) == MATCH_FAILED )
91) return NULL;

92) /* 
93) this is where we do the value assignments for the mib results.
94) */
95) switch(vp->;magic) {
96) case USTSSSIMPLESTRING:
97) *write_method = write_ustSSSimpleString;
98) *var_len = ustSSSimpleString_len;
99) return (unsigned char *) ustSSSimpleString;

100) case USTSSSECONDSSINCECHANGED:
101) /* TimeTicks are seconds*100 */
102) long_ret = (time(NULL) - lastChanged)*100;
103) *var_len = sizeof(long_ret);
104) return (unsigned char *) &long_ret;

105) default:
106) ERROR_MSG("");
107) }
108) return NULL;
109) }

110) int
111) write_ustSSSimpleString(int action,
112) u_char *var_val,
113) u_char var_val_type,
114) size_t var_val_len,
115) u_char *statP,
116) oid *name,
117) size_t name_len)
118) {
119) static unsigned char *new_string = 0, *old_string = 0;
120) static size_t size, old_size;

121) /* this long complex series of "action"s is to preserve proper
122) transaction handling with other transactions in the same set
123) request. */

124) switch ( action ) {
125) case RESERVE1:
126) /* check to see that everything is possible */
127) if (var_val_type != ASN_OCTET_STR){
128) fprintf(stderr, 
129) "write to ustSSSimpleString not ASN_OCTET_STR\n");
130) return SNMP_ERR_WRONGTYPE;
131) }
132) break;

133) case RESERVE2:
134) /* allocate memory needed here. */
135) size = var_val_len;
136) new_string = (char *) malloc(size+1);
137) if (new_string == NULL) {
138) return SNMP_ERR_GENERR; /* malloc failed! */
139) }
140) break;

141) case ACTION:
142) /* Actually make the change requested. Note that
143) anything done here must be reversable in the UNDO case */
144) if (new_string) {
145) old_string = ustSSSimpleString;
146) old_size = ustSSSimpleString_len;
147) memcpy(new_string, var_val, var_val_len);
148) new_string[var_val_len] = 0;
149) ustSSSimpleString = new_string;
150) ustSSSimpleString_len = size;
151) new_string = NULL;
152) } else {
153) /* something seriously wrong if we got here */
154) return SNMP_ERR_GENERR;
155) }
156) break;

157) case UNDO:
158) /* Back out any changes made in the ACTION case */
159) if (old_string == NULL) {
160) return SNMP_ERR_UNDOFAILED;
161) }
162) if (ustSSSimpleString)
163) free(ustSSSimpleString);
164) ustSSSimpleString = old_string;
165) ustSSSimpleString_len = old_size;
166) break;

167) case COMMIT:
168) /* Things are working well, so it's now safe to make the change
169) permanently. Make sure that anything done here can't fail! */
170) lastChanged = time(NULL);
171) break;

172) /* Treat the rest the same as FREE */
173) case FREE:
174) // break;
175) /* Release any resources that have been allocated */
176) if (new_string) {
177) free(new_string);
178) new_string = NULL;
179) }
180) if (old_string) {
181) free(old_string);
182) old_string = NULL;
183) }
184) break;

185) }
186) return SNMP_ERR_NOERROR;
187) }

我們定義的MIB模塊是如此的簡單,我們只需要在mib2c生成的代碼上作黑體標識的修改即可. 下面就三種擴展snmpd的方法展開討論.

snmpd擴展方法一: 靜態鏈接形式

先將生成的兩個文件, ustScalarSet.h和ustScalarSet.c, 拷貝到下載的ucd-snmp源代碼目錄下agent/mibgroup子目錄中. 例如在我的機器上, ucd-snmp 4.2.1的源代碼在/usr/local/src/ucd-snmp-4.2.1中, 相應的拷貝的目標目錄爲, /usr/local/src/ucd-snmp-4.2.1/agent/mibgroup.

在ucd-snmp 4.2.1的主目錄中(我的機器爲/usr/local/src/ucd-snmp-4.2.1), 按如下序列執行命令
# ./configure -with-mib-modules="ustScalarSet"
# make
# make install
這樣, 新的代理程序生成並安裝. 運行SNMP代理程序
# /usr/local/sbin/snmpd
在用相應的工具程序檢索新加入的MIB變量. 可以用如下任何命令:
% /usr/local/bin/snmpget localhost public UCD-SNMP-TUTORIAL-MIB::ustSSSimpleString.0
% /usr/local/bin/snmpwalk localhost public UCD-SNMP-TUTORIAL-MIB::ustScalarSet

snmpd擴展方法二: 共享鏈接庫形式

首先, 在任一目錄下編譯生成共享鏈接庫. 假定目錄爲/usr/local/temp. 將兩個源文件, ustScalarSet.h和ustScalarSet.c拷貝到此目錄下. 按如下命令序列生成共享鏈接庫:
gcc -g -I/usr/local/include -c -o ustScalarSet.o ustScalarSet.c
gcc -g -fPIC -shared -o ustScalarSet.so ustScalarSet.o

有兩種方法在代理程序中動態加載共享鏈接庫. 第一種適合於代理程序已運行的情況, 按如下命令序列執行:
# snmpset localhost hyj UCD-DLMOD-MIB::dlmodStatus.1 i create
# snmpset localhost hyj UCD-DLMOD-MIB::dlmodName.1 s "ustScalarSet" 
# snmpset localhost hyj UCD-DLMOD-MIB::dlmodPath.1 s "/usr/local/temp/ustScalarSet.so"
# snmpset localhost hyj UCD-DLMOD-MIB::dlmodStatus.1 i load
即可裝載.這時可以用工具程序檢索或設置相應的變量. 這裏需要注意的是工具snmpset的用法. 代理snmpd的確省配置, 不支持任何用戶設置變量. 我們可以通過配置文件snmpd.conf中的訪問控制部分進行配置. 我在我的snmpd.conf文件中加入瞭如下兩行:
rwcommunity hyj
rocommunity public
設置了一個讀寫community, hyj和一個只讀community, public. 配置文件確省位於/usr/local/share/snmp目錄下.
第二種, 直接在snmpd.conf中加入一行:
dlmod ustScalarSet /usr/local/temp/ustScalarSet.so
重新啓動snmpd代理, 代理自動裝載共享庫.

關於代理程序以及工具程序相應的配置情況, 參見snmp.conf, snmpd.conf, 和snmpconf的man手冊.

snmpd擴展方法三: AgentX子代理協議

首先, 編寫一個子代理主函數文件, ustMain.c. 如下:

1) #include <ucd-snmp/ucd-snmp-config.h>;
2) #include <ucd-snmp/ucd-snmp-includes.h>;
3) #include <ucd-snmp/ucd-snmp-agent-includes.h>;

4) int main () {
5) int agentx_subagent=1; 

6) snmp_enable_stderrlog();

7) if (agentx_subagent) {
8) ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, 1);
9) }

10) init_agent("ustMain");

11) init_ustScalarSet();

12) init_snmp("ustMain");

13) if (!agentx_subagent)
14) init_master_agent(161, NULL, NULL); 

15) while(1) {
16) agent_check_and_process(1);
17) }

18) snmp_shutdown("ustMain");
19) }

第1-3行, 必須包含的頭文件.

第5行, 定義一個變量, 表示該代理是主代理或子代理. 通過ucd-snmp開發包編寫的代理程序, 既可以作爲AgentX主代理, 也可以作爲AgentX子代理. 下面部分, 我們將嘗試寫一個主代理程序, 如snmpd一樣.

第7-9行, 子代理需要初始化的內容.

第10行, 初始化代理.

第11行, 初始化支持的MIB. 文件ustScalarSet.c中的函數.

第12行, 初始化SNMP.

第13-14行, 主代理需要初始化的內容.

第15-17行, SNMP協議PDU處理主循環.

第18行, 關閉SNMP, 做一些釋放資源的工作.

按如下命令進行編譯:
gcc -g -I/usr/local/include -o ustMain ustMain.c ustScalarSet.c -lucdagent -lucdmibs -lsnmp
生成子代理程序, ustMain.

在snmpd.config配置文件中加入一行:
master agentx
以支持AgentX子代理. 並重新啓動snmpd.
然後啓動 ustMain.

運行相應的工具程序, 測試是否可以訪問新加入的MIB信息.

一個簡單的SNMP代理程序

實際上, 我們可以利用ucd-snmp編寫自己的SNMP代理程序. 如下文件, hsnmpd.c, 所示. 其實, 這個文件與上一個子代理程序完全相同. 我僅僅是將變量agentx_subagent賦成0.
代碼如下.

hsnmpd.c :

1) #include <ucd-snmp/ucd-snmp-config.h>;
2) #include <ucd-snmp/ucd-snmp-includes.h>;
3) #include <ucd-snmp/ucd-snmp-agent-includes.h>;

4) int main () {
5) int agentx_subagent=0; 

6) if (agentx_subagent) {
7) ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, 1);
8) }

9) init_agent("snmpd");

10) init_ustScalarSet();

11) init_snmp("snmpd");

12) if (!agentx_subagent)
13) init_master_agent(161, NULL, NULL); 

14) while(1) {
15) agent_check_and_process(1);
16) }

17) snmp_shutdown("snmpd");
18) }

如下編譯:
gcc -g -I/usr/local/include -o hsnmpd hsnmpd.c ustScalarSet.c /usr/local/lib/libucdagent.a /usr/local/lib/libucdmibs.a /usr/local/lib/libsnmp.a

運行該程序, hsnmpd. 除了一些關於無法解釋配置文件的相關內容的報警外, 程序運行正常. 並且, 可以用工具程序, 如snmpget, snmpwalk等訪問其中的MIB信息. 當然, 僅僅只有UCD-SNMP-TUTORIAL-MIB中所描述的信息, 而其他的沒有實現的MIB信息無法獲得.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章