一.安装及配置SNMP(win32环境)
1.下载
从www.sourceforge下载到最新的net-snmp(目前最新版本5.4.1)net-snmp-5.4.1.zip
2.解压编译
解压后,可以看到有一个win32目录,里面存放的是和win32环境相关的文件,有3个dsw:
libsdll.dsw            编译lib文件和dll文件的工程
win32.dsw            编译lib文件和工具文件如snmpget,snmpset的工程
win32sdk.dsw              类似于win32.dsw,区别在于:需要安装Platform SDK。如果需要agent能支持 interfaces等一些高级功能,必须用此工程编译。XPSP2 Platform SDK的下载地址
www.microsoft/msdownload/platformsdk/sdkupdate/XPSP2FULLInstall.htm
只需要安装Core SDK就可以了,安装完后需要从开始菜单中Register一下。
注意编译的顺序,最好先编译libsdll.dsw,把netsnmp.lib,netsnmpagent.lib,netsnmphelpers.lib,netsnmpmibs.lib,netsnmptrapd.lib文件先编译好,再编译win32sdk.dsw中的项目。
3.安装
运行win32目录下的install-net-snmp.bat批处理文件,会把上一步编译生成的文件及相关的头文件等拷贝到c:\usr目录。
4.配置
在c:\usr\etc\snmp目录添加配置文件f,添加如下内容:
rocommunity  public
rwcommunity  private
它表示的含义是,启动agent服务后,通过public共同体是只读的,private共同体可读也可写。
在命令行运行如下命令,将snmp注册为windows的服务:
cmd>”C:\usr\” –register -Lf "C:/usr/log/snmpd.log"
注册成功后可以在【控制面板】->【管理工具】->【服务】中看到刚注册的服务,服务名是:net-snmp agent
5.运行
cmd>net start “net-snmp agent”
如果正常,会得到启动服务成功的提示
6.验证
cmd>snmpget –v2c –c public localhost 1.3.6.1.2.1.1.5.0
cmd> snmpset -v2c -c private localhost sysContact.0 = piyeyong
如果正常,会的到取得和设置成功的提示,出错会给出错误提示。
二.MIB文件编写
MIB文件会存放于C:\usr\share\snmp\mibs\目录下,是*.txt,纯文本文件,可以直接打开查看和更改。RFC1213中定义的MIB节点信息的定义存放与,这些节点是比较重要的,会经常用
到。
如果要扩展MIB,应该定义在1.3.6.1.4.1(.dod.prises)子树下。自定义MIB的节点,只需要描述该节点的SYNTAX,ACCESS,STATUS,DESCRIPTION等属性及它属于父节点的第几个子节点即可。如下所示,为扩展MIB的一个简单例子:
PROBA-MIB DEFINITIONS::=BEGIN
IMPORTS   
enterprises,OBJECT-TYPE,Integer32,TimeTicks
FROM SNMPv2-SMI
TEXTUAL-CONVENTION,  DisplayString FROM SNMPv2-TC;
-- proba node
proba OBJECT IDENTIFIER::={enterprises 8888}
baseinfo    OBJECT IDENTIFIER ::= { proba 1 }
-- company name
probaCompName OBJECT-TYPE
SYNTAX DisplayString (SIZE (0..255))
ACCESS read-only
STATUS mandatory
DESCRIPTION "The Name of company"
::={baseinfo 1}
-- company location
probaLocation OBJECT-TYPE
SYNTAX DisplayString (SIZE (0..255))
ACCESS read-write
STATUS mandatory
DESCRIPTION "The Location of company"
::={baseinfo 2}
-- employee number
probaEmployeeNumber OBJECT-TYPE
SYNTAX INTEGER
ACCESS read-only
STATUS mandatory
常常的近义词是什么
DESCRIPTION "The number of employee"
::={baseinfo 3}
END
三.Agent端开发
在上一步中定义好MIB的结构后,现在就开始编码实现定义好的节点。net-snmp提供了一个MIB2C工具,利用它可以根据MIB的定义和配置文件自动生成*.c和*.h模板文件,然后只需要在相应位置添加对节点数据的处理就可以了。
1.配置net-snmp的perl模块
用使用mib2c工具,需要perl模块的支持,可以从www.ActiveState/ActivePerl下载,目前最新版是5.8.8
在net-snmp源文件的perl目录下,运行以下命令:
cmd>perl makefile.pl
如果成功,会生成makefile文件
cmd>nmake
cmd>nmake install
这时,会将net-snmp相关的perl模块编译好并安装到c:\perl\site\lib目录下。
注:有时候运行nmake会失败,把其它机器上安装好的c:\perl\site\lib目录下的文件拷贝过来,也可以运行。
2.用mib2c生成模板源代码
运行以下命令:
cmd>mib2c -c f baseinfo
会按照模板配置文件f生成baseinfo.h和baseinfo.c文件。注意:baseinfo是上一步在MIB中定义的proba下的一个节点。在baseinfo.c中有很多/* XXX 注释*/的地方,这些地方是需要我们修改,填上我们对节点数据的处理代码。
3.对read-only节点的代码修改
以probaCompName节点为例:
int
handle_probaCompName(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,
(u_char *)"proba" /* XXX: a pointer to the scalar's data */,
strlen("proba")/* 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_probaCompName\n", reqinfo->mode );
return SNMP_ERR_GENERR;
}
return SNMP_ERR_NOERROR;
}
从上面的代码看出,只需在两处/* XXX 注释 */的代码处填上这个节点的数据即可,管理站在执行get命令时这个值会返回给管理站。
4.对read-write节点的代码修改
以probaLocation节点为例:
static char location[256];
void
init_baseinfo(void)
{
memset(location, '\0', sizeof location);
memcpy(location, "beijing", sizeof "beijing");
。。。。。。
}
int
handle_probaLocation(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info  *reqinfo,
netsnmp_request_info        *requests)
{
int ret;
/* We are never called for a GETNEXT if it's registered as a
"instance", as it's "magically" handled for us.  */
配置windows update失败/* 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,
(u_char *)location /* XXX: a pointer to the scalar's data */,
strlen(location)/* XXX: the length of the data in bytes */);
break;
/*
* SET REQUEST
科目三考试详细步骤
*
* multiple states in the transaction.  See:
* /tutorial-5/toolkit/mib_module/set-actions.jpg
*/
case MODE_SET_RESERVE1:
/* or you could use netsnmp_check_vb_type_and_size instead */
ret = netsnmp_check_vb_type(requests->requestvb, ASN_OCTET_STR);
if ( ret != SNMP_ERR_NOERROR ) {
netsnmp_set_request_error(reqinfo, requests, ret );
}
break;
case MODE_SET_RESERVE2:
/* XXX malloc "undo" storage buffer */
if (0/* XXX if malloc, or whatever, failed: */) {
netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_RESOURCEUNAVAILABLE);
}
break;
case MODE_SET_FREE:
/* XXX: free resources allocated in RESERVE1 and/or
RESERVE2.  Something failed somewhere, a
nd the states
below won't be called. */
break;
case MODE_SET_ACTION:
/
* XXX: perform the value change here */
if (0/* XXX: error? */) {
netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_COMMITFAILED/* some error */);
}
break;张子枫个人资料及作品
case MODE_SET_COMMIT:
/* XXX: delete temporary storage */
memcpy(location, requests->requestvb->buf, requests->requestvb->val_len);
location[requests->requestvb->val_len] = '\0';
if (0/* XXX: error? */) {
/* try _really_really_ hard to never get to this point */
netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_COMMITFAILED);
}
break;
case MODE_SET_UNDO:
/* XXX: UNDO and return to previous value for the object */
if (0/* XXX: error? */) {
/* try _really_really_ hard to never get to this point */
netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_UNDOFAILED);
}
break;
default:
/
* we should never get here, so this is a really bad error */
snmp_log(LOG_ERR, "unknown mode (%d) in handle_probaLocation\n", reqinfo->mode );
return SNMP_ERR_GENERR;
}
return SNMP_ERR_NOERROR;
maroon 5}
对于read-write节点的处理要复杂一点,对每一次管理站的set请求,代理站的处理会经过如下图所示的步骤:
从图中可以看出,通过这种机制,在处理出错的时候,可以根据需要实现回滚操作。
5.重新编译
按照一下步骤重新编译工程:
1)把baseinfo.h和baseinfo.c文件拷贝到net-snmp源文件下agent/mibgroup目录下;
2)打开win32sdk,将其添加到netsnmpmibssdk工程;
3)打开net-snmp源文件下win32目录下的mib_module_includes.h,添加:
#include "mibgroup/proba/baseinfo.h"
4)打开net-snmp源文件下win32目录下的mib_module_inits.h,添加:
if (should_init("baseinfo")) init_baseinfo();
5)重新编译netsnmpmibssdk工程和snmpdsdk工程,把生成的拷贝到c:\usr\bin,netsnmpmibs.lib拷贝到c:\usr\lib
四.管理站开发
以获取sysName节点为例:
struct snmp_session session, *ss;
struct snmp_pdu *pdu;
struct snmp_pdu *response;
oid anOID[MAX_OID_LEN];
size_t anOID_len = MAX_OID_LEN;
struct variable_list *vars;
int status;
/*
* Initialize the SNMP library
*/
init_snmp("snmpapp");
/*
* Initialize a "session" that defines who we're going to talk to
*/
snmp_sess_init( &session );                  /* set up defaults */
session.peername = "loc
alhost";
/* set up the authentication parameters for talking to the server */
#ifdef DEMO_USE_SNMP_VERSION_3
/* Use SNMPv3 to talk to the experimental server */
/* set the SNMP version number */
session.version=SNMP_VERSION_3;
/* set the SNMPv3 user name */
session.securityName = strdup("MD5User");
session.securityNameLen = strlen(session.securityName);
/
* set the security level to authenticated, but not encrypted */
session.securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
/* set the authentication method to MD5 */
session.securityAuthProto = usmHMACMD5AuthProtocol;
session.securityAuthProtoLen = sizeof(usmHMACMD5AuthProtocol)/sizeof(oid);
session.securityAuthKeyLen = USM_AUTH_KU_LEN;
/* set the authentication key to a MD5 hashed version of our
passphrase "The Net-SNMP Demo Password" (which must be at least 8
characters long) */
if (generate_Ku(session.securityAuthProto,
session.securityAuthProtoLen,
(u_char *) our_v3_passphrase, strlen(our_v3_passphrase),
session.securityAuthKey,
&session.securityAuthKeyLen) != SNMPERR_SUCCESS) {
snmp_perror(argv[0]);
snmp_log(LOG_ERR,
"Error generating Ku from authentication pass phrase. \n");
exit(1);
}陈思诚把佟丽娅进贡给谁
#else /* we'll use the insecure (but simplier) SNMPv1 */
/* set the SNMP version number */
session.version = SNMP_VERSION_1;
/
* set the SNMPv1 community name used for authentication */
sessionmunity = (u_char*)"public";
sessionmunity[6] = '\0';
sessionmunity_len = 6;
#endif /* SNMPv1 */
/* windows32 specific initialization (is a noop on unix) */
SOCK_STARTUP;
/*
* Open the session
*/
ss = snmp_open(&session);                    /* establish the session */
if (!ss) {
snmp_perror("ack");
snmp_log(LOG_ERR, "something horrible happened!!!\n");
exit(2);
}
/*
* Create the PDU for the data for our request.
*  1) We're going to GET the system.sysDescr.0 node.
*/
pdu = snmp_pdu_create(SNMP_MSG_GET);
read_objid(".1.3.6.1.2.1.1.5.0", anOID, &anOID_len);
/
/get_node("sysDescr.0", anOID, &anOID_len);
snmp_add_null_var(pdu, anOID, anOID_len);
/*
* Send the Request out.
*/
status = snmp_synch_response(ss, pdu, &response);
/*
* Process the response.
*/
if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
/*
* SUCCESS: Print the result variables
*/
for(vars = response->variables; vars; vars = vars->next_variable)
print_variable(vars->name, vars->name_length, vars);