SNMP:简单网络管理协议编程实现
SNMP:简单网络管理协议(Simple Network Management Protocol),是由互联网工程任务组定义的一套网络管理协议。SNMP可以使网络管理员通过一台工作站完成对计算机、路由器和其他网络设备的远程管理和监视。利用SNMP协议可以更好地管理和监控网络。管理工作站可以远程管理所有支持该协议的网络设备,如监视网络状态、修改网络设备配置、接收网络事件警告等。SNMP作为TCP/IP协议的一部分,其消息是被封装到UDP协议中进行传输的。SNMP协议主要由两大部分组成:网络管理站(也叫管理进程)和被管的网络单元(也叫被管设备),被管设备种类众多,比如:路由器、终端服务器、打印机等。在本文档中,国民技术的N32G457QEL_EVB V1.1全功能开发板就充当被管理设备。被管设备端和管理相关的软件叫代理程序(SNMP agent)或者代理进程,它是运行于设备上的代码或程序。管理进程和代理进程之间的通信可以有两种方式:一种是管理进程向代理进程发起的,询问其具体参数值(get操作)或者为其设置某个参数值(set操作);另一种是代理进程主动向管理进程发起的,向其报告自身的某些重要事件的发生(trap操作)。到目前为止,SNMP共有三个版本:v1,v2和v3。V1和v2有很多共同的特征,v3在前面版本的基础上增强了安全性方面的功能。其各自的消息格式、操作命令等。
NMP系统基本组件SNMP系统基本组件包括网络管理系统NMS(Network Management System)、代理进程(Agent)、被管对象(Managed Object)和管理信息库MIB(Management Information Base)。如图所示他们共同构成SNMP的管理模型,在SNMP的体系结构中都起着至关重要的作用。NMSNMS是网络中扮演管理者,是一个采用SNMP协议对网络设备进行管理/监视的系统,运行在NMS服务器上。
[*]NMS可以向设备上的Agent发出请求,查询或修改一个或多个具体的参数值。
[*]NMS可以接收设备上的Agent主动发送的Trap信息,以获知被管理设备当前的状态。
AgentAgent是被管理设备中的一个代理进程,用于维护被管理设备的信息数据并响应来自NMS的请求,把管理数据汇报给发送请求的NMS。
[*]Agent接收到NMS的请求信息后,通过MIB表完成相应指令后,并把操作结果响应给NMS。
[*]当设备发生故障或者其它事件时,设备会通过Agent主动发送信息给NMS,向NMS报告设备当前的状态变化。
Managed ObjectManaged Object指被管理对象。每一个设备可能包含多个被管理对象,被管理对象可以是设备中的某个硬件,也可以是在硬件、软件(如路由选择协议)上配置的参数集合。
MIBMIB是一个数据库,指明了被管理设备所维护的变量,是能够被Agent查询和设置的信息。MIB在数据库中定义了被管理设备的一系列属性:对象的名称、对象的状态、对象的访问权限和对象的数据类型等。通过MIB,可以完成以下功能:
[*]Agent通过查询MIB,可以获知设备当前的状态信息。
[*]Agent通过修改MIB,可以设置设备的状态参数。
SNMP嵌入式系统实现方法: MCU选用Cotex M3系列STM32F103芯片,以太网控制芯片选用WIZnet的W5500。
主要代码:(附件为整个代码)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "ctype.h"
#include "w5500.h"
#include "socket.h"
#include "config.h"
#include "mcu_int.h"
#include "snmpLib.h"
#include "snmpDemo.h"
struct messageStruct request_msg;
struct messageStruct response_msg;
uint8 errorStatus, errorIndex;
#define COPY_SEGMENT_TEMP20110929(x) \
{ \
request_msg.index += seglen; \
memcpy(&response_msg.buffer, &request_msg.buffer, seglen ); \
response_msg.index += seglen; \
}
void WDEBUG(char *fmt, ...)
{
char zlog_string;
va_list ap;
va_start(ap, fmt);
vsprintf(zlog_string, fmt, ap);
strcat(zlog_string, "\r\n");
printf(zlog_string);
va_end(ap);
}
int32 findEntry(uint8 *oid, int32 len)
{
int32 i;
for (i = 0 ; i < maxData ; i++)
{
if (len == snmpData.oidlen)
{
if (!memcmp(snmpData.oid, oid, len)) return(i);
}
}
return OID_NOT_FOUND;
}
int32 getOID(int32 id, uint8 *oid, uint8 *len)
{
int32 j;
if (!((id >= 0) && (id < maxData))) return INVALID_ENTRY_ID;
*len = snmpData.oidlen;
for (j = 0 ; j < *len ; j++)
{
oid = snmpData.oid;
}
return SUCCESS;
}
int32 getValue( uint8 *vptr, int32 vlen)
{
int32 index = 0;
int32 value = 0;
while (index < vlen)
{
if (index != 0) value <<= 8;
value |= vptr;
}
return value;
}
int32 getEntry(int32 id, uint8 *dataType, void *ptr, int32 *len)
{
if (!((id >= 0) && (id < maxData))) return INVALID_ENTRY_ID;
*dataType = snmpData.dataType;
switch(*dataType)
{
case SNMPDTYPE_OCTET_STRING :
case SNMPDTYPE_OBJ_ID :
{
uint8 *string = ptr;
int32 j;
if (snmpData.getfunction != NULL)
{
snmpData.getfunction( (void *)&snmpData.u.octetstring, &snmpData.dataLen );
}
if ( (*dataType)==SNMPDTYPE_OCTET_STRING )
{
snmpData.dataLen = (uint8)strlen((int8*)&snmpData.u.octetstring);
}
*len = snmpData.dataLen;
for (j = 0 ; j < *len ; j++)
{
string = snmpData.u.octetstring;
}
}
break;
case SNMPDTYPE_INTEGER :
case SNMPDTYPE_TIME_TICKS :
case SNMPDTYPE_COUNTER :
case SNMPDTYPE_GAUGE :
{
int32 *value = ( int32 * )ptr;
if (snmpData.getfunction != NULL)
{
snmpData.getfunction( (void *)&snmpData.u.intval, &snmpData.dataLen );
}
*len = sizeof(uint32);
*value = HTONL(snmpData.u.intval);
}
break;
default :
return INVALID_DATA_TYPE;
}
return SUCCESS;
}
int32 setEntry(int32 id, void *val, int32 vlen, uint8 dataType, int32 index)
{
int32 retStatus=OID_NOT_FOUND;
int32 j;
if (snmpData.dataType != dataType)
{
errorStatus = BAD_VALUE;
errorIndex = index;
return INVALID_DATA_TYPE;
}
switch(snmpData.dataType)
{
case SNMPDTYPE_OCTET_STRING :
case SNMPDTYPE_OBJ_ID :
{
uint8 *string = val;
for (j = 0 ; j < vlen ; j++)
{
snmpData.u.octetstring = string;
}
snmpData.dataLen = vlen;
}
retStatus = SUCCESS;
break;
case SNMPDTYPE_INTEGER :
case SNMPDTYPE_TIME_TICKS :
case SNMPDTYPE_COUNTER :
case SNMPDTYPE_GAUGE :
{
snmpData.u.intval = getValue( (uint8 *)val, vlen);
snmpData.dataLen = vlen;
if (snmpData.setfunction != NULL)
{
snmpData.setfunction(snmpData.u.intval);
}
}
retStatus = SUCCESS;
break;
default :
retStatus = INVALID_DATA_TYPE;
break;
}
return retStatus;
}
int32 parseLength(const uint8 *msg, int32 *len)
{
int32 i=1;
if (msg & 0x80)
{
int32 tlen = (msg & 0x7f) - 1;
*len = msg;
while (tlen--)
{
*len <<= 8;
*len |= msg;
}
}
else
{
*len = msg;
}
return i;
}
int32 parseTLV(const uint8 *msg, int32 index, tlvStructType *tlv)
{
int32 Llen = 0;
tlv->start = index;
Llen = parseLength((const uint8 *)&msg, &tlv->len );
tlv->vstart = index + Llen + 1;
switch (msg)
{
case SNMPDTYPE_SEQUENCE:
case GET_REQUEST:
case GET_NEXT_REQUEST:
case SET_REQUEST:
tlv->nstart = tlv->vstart;
break;
default:
tlv->nstart = tlv->vstart + tlv->len;
break;
}
return 0;
}
void insertRespLen(int32 reqStart, int32 respStart, int32 size)
{
int32 indexStart, lenLength;
uint32 mask = 0xff;
int32 shift = 0;
if (request_msg.buffer & 0x80)
{
lenLength = request_msg.buffer & 0x7f;
indexStart = respStart+2;
while (lenLength--)
{
response_msg.buffer =
(uint8)((size & mask) >> shift);
shift+=8;
mask <<= shift;
}
}
else
{
response_msg.buffer = (uint8)(size & 0xff);
}
}
int32 parseVarBind(int32 reqType, int32 index)
{
int32 seglen = 0, id;
tlvStructType name, value;
int32 size = 0;
extern const int32 maxData;
parseTLV(request_msg.buffer, request_msg.index, &name);
if ( request_msg.buffer != SNMPDTYPE_OBJ_ID ) return -1;
id = findEntry(&request_msg.buffer, name.len);
if ((reqType == GET_REQUEST) || (reqType == SET_REQUEST))
{
seglen = name.nstart - name.start;
COPY_SEGMENT_TEMP20110929(name);
size = seglen;
}
else if (reqType == GET_NEXT_REQUEST)
{
response_msg.buffer = request_msg.buffer;
if (++id >= maxData)
{
id = OID_NOT_FOUND;
seglen = name.nstart - name.start;
COPY_SEGMENT_TEMP20110929(name);
size = seglen;
}
else
{
request_msg.index += name.nstart - name.start;
getOID(id, &response_msg.buffer, &response_msg.buffer);
seglen = response_msg.buffer+2;
response_msg.index += seglen ;
size = seglen;
}
}
parseTLV(request_msg.buffer, request_msg.index, &value);
if (id != OID_NOT_FOUND)
{
uint8 dataType;
int32 len;
if ((reqType == GET_REQUEST) || (reqType == GET_NEXT_REQUEST))
{
getEntry(id, &dataType, &response_msg.buffer, &len);
response_msg.buffer = dataType;
response_msg.buffer = len;
seglen = (2 + len);
response_msg.index += seglen;
request_msg.index += (value.nstart - value.start);
}
else if (reqType == SET_REQUEST)
{
setEntry(id, &request_msg.buffer, value.len, request_msg.buffer, index);
seglen = value.nstart - value.start;
COPY_SEGMENT_TEMP20110929(value);
}
}
else
{
seglen = value.nstart - value.start;
COPY_SEGMENT_TEMP20110929(value);
errorIndex = index;
errorStatus = NO_SUCH_NAME;
}
size += seglen;
return size;
}
int32 parseSequence(int32 reqType, int32 index)
{
int32 seglen;
tlvStructType seq;
int32 size = 0, respLoc;
parseTLV(request_msg.buffer, request_msg.index, &seq);
if ( request_msg.buffer != SNMPDTYPE_SEQUENCE ) return -1;
seglen = seq.vstart - seq.start;
respLoc = response_msg.index;
COPY_SEGMENT_TEMP20110929(seq);
size = parseVarBind( reqType, index );
insertRespLen(seq.start, respLoc, size);
size += seglen;
return size;
}
int32 parseSequenceOf(int32 reqType)
{
int32 seglen;
tlvStructType seqof;
int32 size = 0, respLoc;
int32 index = 0;
parseTLV(request_msg.buffer, request_msg.index, &seqof);
if ( request_msg.buffer != SNMPDTYPE_SEQUENCE_OF ) return -1;
seglen = seqof.vstart - seqof.start;
respLoc = response_msg.index;
COPY_SEGMENT_TEMP20110929(seqof);
while (request_msg.index < request_msg.len)
{
size += parseSequence( reqType, index++ );
}
insertRespLen(seqof.start, respLoc, size);
return size;
}
int32 parseRequest()
{
int32 ret, seglen;
tlvStructType snmpreq, requestid, errStatus, errIndex;
int32 size = 0, respLoc, reqType;
parseTLV(request_msg.buffer, request_msg.index, &snmpreq);
reqType = request_msg.buffer;
if ( !VALID_REQUEST(reqType) ) return -1;
seglen = snmpreq.vstart - snmpreq.start;
respLoc = snmpreq.start;
size += seglen;
COPY_SEGMENT_TEMP20110929(snmpreq);
response_msg.buffer = GET_RESPONSE;
parseTLV(request_msg.buffer, request_msg.index, &requestid);
seglen = requestid.nstart - requestid.start;
size += seglen;
COPY_SEGMENT_TEMP20110929(requestid);
parseTLV(request_msg.buffer, request_msg.index, &errStatus);
seglen = errStatus.nstart - errStatus.start;
size += seglen;
COPY_SEGMENT_TEMP20110929(errStatus);
parseTLV(request_msg.buffer, request_msg.index, &errIndex);
seglen = errIndex.nstart - errIndex.start;
size += seglen;
COPY_SEGMENT_TEMP20110929(errIndex);
ret = parseSequenceOf(reqType);
if (ret == -1) return -1;
else size += ret;
insertRespLen(snmpreq.start, respLoc, size);
if (errorStatus)
{
response_msg.buffer = errorStatus;
response_msg.buffer = errorIndex + 1;
}
return size;
}
int32 parseCommunity()
{
int32 seglen;
tlvStructType community;
int32 size=0;
parseTLV(request_msg.buffer, request_msg.index, &community);
if (!((request_msg.buffer == SNMPDTYPE_OCTET_STRING) && (community.len == COMMUNITY_SIZE)))
{
return -1;
}
if (!memcmp(&request_msg.buffer, (int8 *)COMMUNITY, COMMUNITY_SIZE))
{
seglen = community.nstart - community.start;
size += seglen;
COPY_SEGMENT_TEMP20110929(community);
size += parseRequest();
}
else
{
return -1;
}
return size;
}
int32 parseVersion()
{
int32 size = 0, seglen;
tlvStructType tlv;
size = parseTLV(request_msg.buffer, request_msg.index, &tlv);
if (!((request_msg.buffer == SNMPDTYPE_INTEGER) && (request_msg.buffer == SNMP_V1)))
return -1;
seglen = tlv.nstart - tlv.start;
size += seglen;
COPY_SEGMENT_TEMP20110929(tlv);
size = parseCommunity();
if (size == -1) return size;
else return (size + seglen);
}
int32 parseSNMPMessage()
{
int32 size = 0, seglen, respLoc;
tlvStructType tlv;
parseTLV(request_msg.buffer, request_msg.index, &tlv);
if (request_msg.buffer != SNMPDTYPE_SEQUENCE_OF) return -1;
seglen = tlv.vstart - tlv.start;
respLoc = tlv.start;
COPY_SEGMENT_TEMP20110929(tlv);
size = parseVersion();
if (size == -1) return -1;
else size += seglen;
insertRespLen(tlv.start, respLoc, size);
return 0;
}
void dumpCode(int8* header, int8* tail, unsigned char *buff, int len)
{
int i;
printf(header);
for (i=0; i<len; i++)
{
if ( i%16==0 ) printf("0x%04x : ", i);
printf("%02x ",buff);
if ( i%16-15==0 )
{
int j;
printf("");
for (j=i-15; j<=i; j++)
{
if ( isprint(buff) ) printf("%c", buff);
else printf(".");
}
printf("\r\n");
}
}
if ( i%16!=0 )
{
int j;
int spaces=(len-i+16-i%16)*3+2;
for (j=0; j<spaces; j++) printf(" ");
for (j=i-i%16; j<len; j++)
{
if ( isprint(buff) ) printf("%c", buff);
else printf(".");
}
}
printf(tail);
}
void ipToByteArray(int8 *ip, uint8 *pDes)
{
uint32 i, ip1=0, ip2=0, ip3=0, ip4=0;
int8 buff;
uint32 len = (uint32)strlen(ip);
strcpy(buff, ip);
for (i=0; i<len; i++)
{
if ( buff=='.' ) buff = ' ';
}
sscanf(buff, "%u %u %u %u", &ip1, &ip2, &ip3, &ip4);
pDes = ip1; pDes = ip2; pDes = ip3; pDes = ip4;
}
int32 makeTrapVariableBindings(dataEntryType *oid_data, void *ptr, uint32 *len)
{
uint32 j;
((uint8*)ptr) = 0x30;
((uint8*)ptr) = 0xff;
((uint8*)ptr) = 0x06;
((uint8*)ptr) = oid_data->oidlen;
for (j = 0 ; j < oid_data->oidlen ; j++)
{
((uint8*)ptr) = oid_data->oid;
}
switch(oid_data->dataType)
{
case SNMPDTYPE_OCTET_STRING :
case SNMPDTYPE_OBJ_ID :
{
uint8 *string = &((uint8*)ptr);
if ( oid_data->dataType==SNMPDTYPE_OCTET_STRING )
{
oid_data->dataLen = (uint8)strlen((int8*)&oid_data->u.octetstring);
}
for (j = 0 ; j < oid_data->dataLen ; j++)
{
string = oid_data->u.octetstring;
}
((uint8*)ptr) = oid_data->dataType;
((uint8*)ptr) = oid_data->dataLen;
((uint8*)ptr) = 2 + oid_data->oidlen + 2 + oid_data->dataLen;
*len = 4 + oid_data->oidlen + 2 + oid_data->dataLen;
}
break;
case SNMPDTYPE_INTEGER :
case SNMPDTYPE_TIME_TICKS :
case SNMPDTYPE_COUNTER :
case SNMPDTYPE_GAUGE :
{
oid_data->dataLen = 4;
*(int32*)(&((uint8*)ptr)) = HTONL(oid_data->u.intval);
((uint8*)ptr) = oid_data->dataType;
((uint8*)ptr) = oid_data->dataLen;
((uint8*)ptr) = 2 + oid_data->oidlen + 2 + oid_data->dataLen;
*len = 4 + oid_data->oidlen + 2 + oid_data->dataLen;
}
break;
default :
return INVALID_DATA_TYPE;
}
return SUCCESS;
}
int32 SnmpXInit()
{
// initTable();
// LED3=0;
return 0;
}
uint8 packet_trap = {0,};
int32 SnmpXTrapSend(int8* managerIP, int8* agentIP, int8* community, dataEntryType enterprise_oid, uint32 genericTrap, uint32 specificTrap, uint32 va_count, ...)
{
uint32 i;
int32 packet_index = 0;
int32 packet_buff1 = 0;
int32 packet_buff2 = 0;
int32 packet_buff3 = 0;
uint8 trap_agentip = {0,};
ipToByteArray(agentIP, trap_agentip);
packet_trap = 0x30; // ASN.1 Header
packet_trap = 0xff; // pdu_length, temp
packet_buff1 = packet_index++;
packet_trap = 0x02; // Version
packet_trap = 0x01;
packet_trap = 0x00;
packet_trap = 0x04; // Community
packet_trap = (uint8)strlen(community);
memcpy(&(packet_trap), community, strlen(community));
packet_index = packet_index + (uint8)strlen(community);
packet_trap = 0xa4; // trap
packet_trap = 0xff; // length, temp
packet_buff2 = packet_index++;
packet_trap = 0x06; // enterprise_oid
packet_trap = enterprise_oid.oidlen;
for (i=0; i<enterprise_oid.oidlen; i++)
{
packet_trap = enterprise_oid.oid;
}
packet_trap = 0x40; // agent ip
packet_trap = 0x04;
packet_trap = trap_agentip;
packet_trap = trap_agentip;
packet_trap = trap_agentip;
packet_trap = trap_agentip;
packet_trap = 0x02; // Generic Trap
packet_trap = 0x01;
packet_trap = (uint8)genericTrap;
packet_trap = 0x02; // Specific Trap
packet_trap = 0x01;
packet_trap = (uint8)specificTrap;
packet_trap = 0x43; // Timestamp
packet_trap = 0x01;
packet_trap = 0x00;
packet_trap = 0x30; // Sequence of variable-bindings
packet_trap = 0xff;
packet_buff3 = packet_index++;
// variable-bindings
{
va_list ap;
uint32 length_var_bindings = 0;
uint32 length_buff = 0;
va_start (ap, va_count);
for (i=0; i<va_count; i++)
{
dataEntryType* fff = va_arg(ap, dataEntryType*);
makeTrapVariableBindings(fff, &(packet_trap), &length_buff);
packet_index = packet_index + length_buff;
length_var_bindings = length_var_bindings + length_buff;
}
packet_trap = length_var_bindings;
va_end (ap);
}
packet_trap = packet_index - 2;
packet_trap = packet_index - (9 + (uint8)strlen(community));
// Send Packet
{
uint8 svr_addr;
//UDPOpen(SOCK_SNMP, 162);
socket(SOCK_SNMP,Sn_MR_UDP,162,0);
ipToByteArray(managerIP, svr_addr);
sendto(SOCK_SNMP, packet_trap, packet_index, svr_addr, 162);
close(SOCK_SNMP);
return 0;
}
}
int32 SnmpXDaemon()
{
int32 snmpfd = 0;
int32 fromlen = 0;
int32 retStatus = 0;
int32 len = 0;
uint8 loopsnmpd = 1;
uint8 svr_addr;
uint16svr_port;
UNUSED(snmpfd);
UNUSED(fromlen);
UNUSED(retStatus);
// UDPOpen(SOCK_SNMP, 161);
socket(SOCK_SNMP,Sn_MR_UDP,161,0);
WDEBUG("Start SNMP Daemon(Agent) ");
while(loopsnmpd)
{
if ( (len = getSn_RX_RSR(SOCK_SNMP))>0 )
{
request_msg.len= recvfrom(SOCK_SNMP, (uint8 *)&request_msg.buffer, len, svr_addr, &svr_port);
}
else
{
request_msg.len = 0;
continue;
}
if (request_msg.len > 0)
{
dumpCode("\r\n\r\n", "\r\n", request_msg.buffer, request_msg.len);
request_msg.index = 0;
response_msg.index = 0;
errorStatus = errorIndex = 0;
if (parseSNMPMessage() != -1)
{
sendto(SOCK_SNMP, response_msg.buffer, response_msg.index, svr_addr, svr_port);
}
dumpCode("\r\n\r\n", "\r\n", response_msg.buffer, response_msg.index);
}
}
close(SOCK_SNMP);
return(0);
}
谢楼主,正在做snmp,参考一下
页:
[1]