关于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_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,208)">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: wjhardaker@ucdavis.edu
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,2021,13,4242,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 } },208)">42) #define USTSSSECONDSSINCECHANGED 2
43) { USTSSSECONDSSINCECHANGED,ASN_TIMETICKS,RONLY,{ 2 } },208)">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,208)">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,208)">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,208)">82) size_t *length,208)">83) int exact,208)">84) size_t *var_len,208)">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,208)">112) u_char *var_val,208)">113) u_char var_val_type,208)">114) size_t var_val_len,208)">115) u_char *statP,208)">116) oid *name,208)">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,208)">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 :
5) int agentx_subagent=0;
6) if (agentx_subagent) {
7) ds_set_boolean(DS_APPLICATION_ID,208)">8) }
9) init_agent("snmpd");
10) init_ustScalarset();
11) init_snmp("snmpd");
12) if (!agentx_subagent)
13) init_master_agent(161,208)">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信息无法获得.
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_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,208)">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: wjhardaker@ucdavis.edu
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,2021,13,4242,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 } },208)">42) #define USTSSSECONDSSINCECHANGED 2
43) { USTSSSECONDSSINCECHANGED,ASN_TIMETICKS,RONLY,{ 2 } },208)">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,208)">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,208)">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,208)">82) size_t *length,208)">83) int exact,208)">84) size_t *var_len,208)">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,208)">112) u_char *var_val,208)">113) u_char var_val_type,208)">114) size_t var_val_len,208)">115) u_char *statP,208)">116) oid *name,208)">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,208)">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 :
5) int agentx_subagent=0;
6) if (agentx_subagent) {
7) ds_set_boolean(DS_APPLICATION_ID,208)">8) }
9) init_agent("snmpd");
10) init_ustScalarset();
11) init_snmp("snmpd");
12) if (!agentx_subagent)
13) init_master_agent(161,208)">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信息无法获得.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。