/****************************************/
/*Title:    snmp.c                      */
/*Descr:    SNMP Agent                  */
/*Author:   Liang Hanxi                 */
/*Create:   2002-4-1                    */
/*Modify:   2003-5-16                   */
/****************************************/
#include	"./include/heartbeat.h"
#include	"./include/snmpv3AuthCry.h"

// fix multiple definition====================================
char				SnmpVer[16];
//

extern BYTE				snmpDebugFull;
static BYTE				initonce = 0; 
static BYTE				fun_num = 0; 
static trapcall			trap_proc[100]; 
static mib_nod			*phead = NULL; 
static BYTE				setcall_num = 0, getcall_num = 0, trapcall_num = 0, rspcall_num = 0; 
static short			SnmpPort = 4957;
snmp_csta				SnmpCsta[96]; 
int						snmp_ins; 
BYTE					snmpVersion=SNMP_V2;
snmp_mib				SnmpMib; 
static snmp_csta		*pCsta; 
snmp_log_info			*pLogInfo;
snmpV3SecurityPara 		v3_engine[MAX_ENGINE];
char					snmpconfile[] = {"./conf/snmp.conf"};
BYTE securityEngineID[32];
snmpV3SecurityPara 		manager_engine;

extern struct timeval	tvnow;

//Private Functions------------------>
static int get_len(BYTE *asnbuf, int *len); 
static int parse_snmpmsg(BYTE *msgin, int msglen, snmp_pdu *psnmp, BYTE *error_status); 
static int build_snmpmsg(BYTE *pbuf, snmp_pdu *psnmp, DWORD ip, WORD port); 
static DWORD assign_rid(); 
static BYTE *getmem(int nsize); 
static int trap_handle(BYTE oidlen, DWORD *oid, BYTE *pdata, WORD datalen, snmp_addr *addr); 
static int rsp_handle(BYTE oidlen, DWORD *oid, snmp_pdu *pdu, snmp_addr *addr); 
static int snmp_handle(BYTE oidlen, DWORD *oid, snmp_pdu *pdu, snmp_addr *addr); 
static void snmp_hb_init(); 
void init_engine_para();
int init_engine(char * engine_name);
void snmp_readpara();

void update_engine_authtime();
int find_engine_server(char *userName, DWORD ip);
int find_engine(char * userName);
int load_engine_para(snmp_pdu * engine, DWORD ip, WORD port);


extern void password_to_key_md5(
        unsigned char *password,
        unsigned int passwordlen,
        unsigned char *engineID,
        unsigned int engineLength,
        unsigned char *key);
/*-----------------------------------------*/

#ifdef _EWS_H_
extern void  ews_proc_heartbeat(BYTE oidLen,DWORD *oid, WORD dataLen,BYTE *pdata);
#endif

void snmp_log_init()
{
	int		shm_id,loop;
	FILE	*fpLog;
	
	shm_id = shmget(SNMP_SHM_KEY+wxc2_get_shm_offset(),32*1024,SNMP_SHM_PERM | IPC_CREAT);
	if(shm_id == -1)
	{
		printf("Failed to create snmp shmmem\n");
		exit(1);
	}
	pLogInfo = (snmp_log_info *)shmat(shm_id,(char *)0,0);
	if(pLogInfo == (void *)-1)
	{
		printf("Failed to shmat snmp shmmem\n");
		exit(2);
	}
	
	fpLog = fopen("../log/snmp_log.txt","w");
	if(fpLog == NULL) return;

	fprintf(fpLog,"--------   SNMP log info   -------\n");
	fprintf(fpLog,"----------------------------------\n");
	fprintf(fpLog,"---> Lastest log No. = %02d <-----\n",
			 (pLogInfo->currentNo+MAX_SNMP_RECORD-1)%MAX_SNMP_RECORD);
	for(loop=0;loop<MAX_SNMP_RECORD;loop++)
	{
		fprintf(fpLog,"-- %s\n",pLogInfo->log_info[loop]);
	}
	fprintf(fpLog,"-------------  End  --------------\n");
	memset(pLogInfo,0,sizeof(snmp_log_info));
	fclose(fpLog);
}

void snmpLogInfo(char *logInfo)
{
	static int currentNo=0;
	sprintf(pLogInfo->log_info[currentNo]," %02d->%s",
	currentNo,logInfo);
	currentNo ++;
	currentNo %= MAX_SNMP_RECORD;
	pLogInfo->currentNo = currentNo;
}

unsigned long long SNMPSerialNumber;
BYTE	snmp_synctime_flag;

void snmp_init(WORD nport)
{
	long		l_time; 
	struct tm			*t; 
	BYTE				version[3] = SNMP_VERSION; 

	SnmpPort = nport;
	if(initonce == 1)
		return; 
	sprintf(SnmpVer, "V%d.%d.%02d", version[0], version[1], version[2]); 

	memset(trap_proc, 0, 100 * sizeof(trapcall)); 

	l_time = time(NULL); 
	t = localtime(&l_time);
	snmp_ins = t->tm_hour * 4 + t->tm_min/15; 
	memset(&SnmpCsta[0], 0, sizeof(snmp_csta) * 96); 
	pCsta = &SnmpCsta[snmp_ins]; 
	pCsta->timestamp = time(NULL); 

	snmpmib_init(); 
	snmp_debug_setup(); 
	snmp_debug_csta(1, snmp_ins); 
	snmp_log_init();
	snmp_readpara();
	init_engine_para();


	SNMPSerialNumber = 0;
	snmp_synctime_flag = 1;//default to sync omc time

	printf("SNMP Agent Version %s ...... Finish initialization!\n", SnmpVer); 
	initonce = 1; 
}

ull  Str2Ull(char *pStr);
void snmp_init_serial_number(char *Serial)
{
	SNMPSerialNumber = Str2Ull(Serial);
}

void snmp_set_timenosync()//call of this function will tell snmp module do not sync the omc time
{
	snmp_synctime_flag = 0;
}

void snmp_timer()
{
	static message_list		msgin; 
	static snmp_pdu			snmpmsg; 
	static snmp_addr		addr; 
	static var_list			*pvar; 
	static int				len; 
	static DWORD			*poid; 
	static BYTE				idlen; 
	int						i, j, loop = 10; 
	struct tm				*t; 
	long			l_time;
	static DWORD 			time_counter=0;
	static BYTE				m_state = 0, ch;//watch_point;
	
	BYTE 				err_status=0;
#if SNMP_DEBUG_LOG
	char					debugBuf[512];
#endif
	//add by yizane start
	DWORD	 in_oid[OID_MAXLEN];
	//add by yizane end

	snmpDebugFull = 0;
	snmp_debug_timer(); 
	if(m_state++ == 25)		//switch csta buffer
	{
		l_time = time(NULL); 
		t = localtime(&l_time); 
		if(ch == 0 && t->tm_min%15 == 0)
		{
			snmp_ins = t->tm_hour * 4 + t->tm_min/15; 
			pCsta = &SnmpCsta[snmp_ins]; 
			memset(pCsta, 0, sizeof(snmp_csta)); 
			pCsta->timestamp = l_time; 
			snmp_debug_csta(1, snmp_ins); 
			ch = 1; 
		}
		if(t->tm_min%15 == 1)
			ch = 0; 
		m_state = 0; 
	}

		time_counter++;
	if(time_counter==100)// 1 secend
	{
		time_counter=0;
		update_engine_authtime();

	}

	while(loop-- > 0)
	{
		if(iptrGetMessage(&msgin, SnmpPort) != 1)
			return;
		
		strcpy(snmpmsg.community, "public"); 
		snmpmsg.error_status = snmpmsg.error_index = 0;

#if SNMP_DEBUG_LOG
		snmpLogInfo("snmp_timer() entering parse_snmpmsg()");
#endif

		if(parse_snmpmsg(msgin.msgContent, msgin.msgLength, &snmpmsg, &err_status) == -1)
		{
			pCsta->fail_parse++; 
			snmp_debug(SNMPDB_ERR, "Fail to parse message1.Give up dealing with it!, src ip=%x, src port=%d, dst port=%d", msgin.msgSrcIP,msgin.msgSrcPort,msgin.msgDstPort); 
			snmp_showbuf(SNMPDB_ERR, msgin.msgContent, msgin.msgLength); 
			continue; 
		}

		//store address
		addr.remote_ip = msgin.msgSrcIP; 
		addr.remote_port = msgin.msgSrcPort; 
		addr.local_ip = msgin.msgDstIP; 
		addr.local_port = msgin.msgDstPort; 
		
		snmp_logmsg(SNMPDB_IN, &snmpmsg, &addr); 

#if SNMP_DEBUG_LOG
		sprintf(debugBuf,"msgIN type: %d , %08lx.%04d from %08lx.%04d",
				snmpmsg.pdu_type,
				msgin.msgSrcIP,msgin.msgSrcPort,
				msgin.msgDstIP,msgin.msgDstPort);
		snmpLogInfo(debugBuf);
		sprintf(debugBuf,"oidLen: %d, lastest 8 oid=%ld.%ld.%ld.%ld.%ld.%ld.%ld.%ld",
				snmpmsg.var[0].oidlen,
				snmpmsg.var[0].oid[snmpmsg.var[0].oidlen-9],
				snmpmsg.var[0].oid[snmpmsg.var[0].oidlen-8],
				snmpmsg.var[0].oid[snmpmsg.var[0].oidlen-7],
				snmpmsg.var[0].oid[snmpmsg.var[0].oidlen-6],
				snmpmsg.var[0].oid[snmpmsg.var[0].oidlen-5],
				snmpmsg.var[0].oid[snmpmsg.var[0].oidlen-4],
				snmpmsg.var[0].oid[snmpmsg.var[0].oidlen-3],
				snmpmsg.var[0].oid[snmpmsg.var[0].oidlen-2]);
		snmpLogInfo(debugBuf);
#endif

		
		if((snmpmsg.msgVersion == SNMP_V3)&&( ((snmpmsg.msgSecurityParameters.seqFlag&1)==0) ||((snmpmsg.msgGlobalData.msgFlags&4)&&memcmp(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineID, manager_engine.securityEngineID, 12)!=0)))
		{//send report
			var_list report_state=
			{
				.oid={1,3,6,1,6,3,15,1,1,4,0},//{1,3,6,1,4,1,1373,2,3,2},//PLATFORM_HB_OID,
				.oidlen=11,//PLATFORM_HB_LEN,
				.vartype=0x41,
				.msglen=1,
				.msg={6}				
			};
			snmpmsg.msgSecurityParameters.seqFlag |=1;
			//memcpy(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineID, securityEngineID, 32); //pierre
			memcpy(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineID, manager_engine.securityEngineID, 32);
			snmpmsg.pdu_type = PDU_REPORT;
			snmpmsg.var_num = 1;
			memcpy(&snmpmsg.var, &report_state, sizeof(var_list));
			snmpmsg.msgData.plaintext.seqFlag = 1;// contextEngineID
			//memcpy(snmpmsg.msgData.plaintext.contextEngineID, securityEngineID, 32); //pierre
			memcpy(snmpmsg.msgData.plaintext.contextEngineID, manager_engine.securityEngineID, 32);
			snmpmsg.msgSecurityParameters.msgAuthoritativeEngineTime= manager_engine.authInTime; //0x02a097;
			snmpmsg.msgSecurityParameters.msgAuthoritativeEngineBoots = manager_engine.boots;
			len = build_snmpmsg(msgin.msgContent, &snmpmsg, addr.remote_ip, addr.remote_port); 
			msgin.msgLength = len; 

			msgin.msgDstIP = addr.remote_ip; 
			msgin.msgDstPort = addr.remote_port; 
			msgin.msgSrcPort = addr.local_port; 
			snmp_logmsg(SNMPDB_OUT, &snmpmsg, &addr); 
			iptrPlatPutMessage(msgin); 
			continue;
		}
		if(snmpmsg.msgVersion == SNMP_V3 && (snmpmsg.msgGlobalData.msgFlags&4)!=0 && (snmpmsg.msgGlobalData.msgFlags&1)!=0)
		{//send report
			if((snmpmsg.msgSecurityParameters.msgAuthoritativeEngineTime>manager_engine.authInTime&&\
				(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineTime-manager_engine.authInTime)>150)||\
				(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineTime<manager_engine.authInTime&&\
				(manager_engine.authInTime-snmpmsg.msgSecurityParameters.msgAuthoritativeEngineTime)>150)\
				||(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineTime==0&&snmpmsg.msgSecurityParameters.msgAuthoritativeEngineBoots==0))
			{
				int index;
				var_list report_state=
					{
						.oid={1,3,6,1,6,3,15,1,1,2,0},//{1,3,6,1,4,1,1373,2,3,2},//PLATFORM_HB_OID,
						.oidlen=11,//PLATFORM_HB_LEN,
						.vartype=0x41,
						.msglen=1,
						.msg={1}				
					};

				index = find_engine(snmpmsg.msgSecurityParameters.msgUserName);
				

				if(index>=0)
				{
					if(v3_engine[index].engineType!=2)// type==2 is internal snmp_v3, it need not check time 
					{

						snmpmsg.msgGlobalData.msgFlags &=1;
						snmpmsg.msgSecurityParameters.seqFlag |=1;
						//memcpy(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineID, securityEngineID, 32); //pierre
						memcpy(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineID, v3_engine[index].securityEngineID, 32);
						snmpmsg.pdu_type = PDU_REPORT;
						snmpmsg.var_num = 1;
						//report_state.msglen = encode_integer(report_state.msg ,  manager_engine.authInTime);
						memcpy(&snmpmsg.var, &report_state, sizeof(var_list));
						snmpmsg.msgData.plaintext.seqFlag = 1;// contextEngineID
						//memcpy(snmpmsg.msgData.plaintext.contextEngineID, securityEngineID, 32); //pierre
						memcpy(snmpmsg.msgData.plaintext.contextName, v3_engine[index].contextName, 32);
						memcpy(snmpmsg.msgData.plaintext.contextEngineID, v3_engine[index].securityEngineID, 32);
						snmpmsg.msgSecurityParameters.msgAuthoritativeEngineTime= manager_engine.authInTime; //0x02a097;
						snmpmsg.msgSecurityParameters.msgAuthoritativeEngineBoots = manager_engine.boots;
						
						len = build_snmpmsg(msgin.msgContent, &snmpmsg, addr.remote_ip, addr.remote_port); 
						msgin.msgLength = len; 

						msgin.msgDstIP = addr.remote_ip; 
						msgin.msgDstPort = addr.remote_port; 
						msgin.msgSrcPort = addr.local_port; 
						snmp_logmsg(SNMPDB_OUT, &snmpmsg, &addr); 
						iptrPlatPutMessage(msgin); 
						continue;
					}
				}
			}
		}
		
		if(snmpmsg.msgVersion == SNMP_V3 && (snmpmsg.msgGlobalData.msgFlags&4)!=0)
		{//send report
			int index;
			var_list report_state=
					{
						.oid={1,3,6,1,6,3,15,1,1,1,0},//{1,3,6,1,4,1,1373,2,3,2},//PLATFORM_HB_OID,
						.oidlen=11,//PLATFORM_HB_LEN,
						.vartype=0x41,
						.msglen=1,
						.msg={1}				
					};

				index = find_engine(snmpmsg.msgSecurityParameters.msgUserName);
				

				if(index<0)
				{
					//if(v3_engine[index].engineType!=2)
					//{
						report_state.oid[9]=3;
						snmpmsg.msgGlobalData.msgFlags &=1;
						snmpmsg.msgSecurityParameters.seqFlag |=1;
						//memcpy(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineID, securityEngineID, 32); //pierre
						//memcpy(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineID, v3_engine[index].securityEngineID, 32);
						snmpmsg.pdu_type = PDU_REPORT;
						snmpmsg.var_num = 1;
						//report_state.msglen = encode_integer(report_state.msg ,  manager_engine.authInTime);
						memcpy(&snmpmsg.var, &report_state, sizeof(var_list));
						snmpmsg.msgData.plaintext.seqFlag = 1;// contextEngineID
						//memcpy(snmpmsg.msgData.plaintext.contextEngineID, securityEngineID, 32); //pierre
						//memcpy(snmpmsg.msgData.plaintext.contextName, v3_engine[index].contextName, 32);
						//memcpy(snmpmsg.msgData.plaintext.contextEngineID, v3_engine[index].securityEngineID, 32);
						snmpmsg.msgSecurityParameters.msgAuthoritativeEngineTime= manager_engine.authInTime; //0x02a097;
						snmpmsg.msgSecurityParameters.msgAuthoritativeEngineBoots = manager_engine.boots;
						
						len = build_snmpmsg(msgin.msgContent, &snmpmsg, addr.remote_ip, addr.remote_port); 
						msgin.msgLength = len; 

						msgin.msgDstIP = addr.remote_ip; 
						msgin.msgDstPort = addr.remote_port; 
						msgin.msgSrcPort = addr.local_port; 
						snmp_logmsg(SNMPDB_OUT, &snmpmsg, &addr); 
						iptrPlatPutMessage(msgin); 
						continue;
					//}					
						
				}
				else if(v3_engine[index].securityLevel!=(snmpmsg.msgGlobalData.msgFlags&3) && (v3_engine[index].engineType!=2))
				{
					if(snmpmsg.var_num!=0)
					{

						snmpmsg.msgGlobalData.msgFlags &=1;
						snmpmsg.msgSecurityParameters.seqFlag |=1;
						//memcpy(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineID, securityEngineID, 32); //pierre
						memcpy(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineID, v3_engine[index].securityEngineID, 32);
						snmpmsg.pdu_type = PDU_REPORT;
						snmpmsg.var_num = 1;
						//report_state.msglen = encode_integer(report_state.msg ,  manager_engine.authInTime);
						memcpy(&snmpmsg.var, &report_state, sizeof(var_list));
						snmpmsg.msgData.plaintext.seqFlag = 1;// contextEngineID
						//memcpy(snmpmsg.msgData.plaintext.contextEngineID, securityEngineID, 32); //pierre
						//memcpy(snmpmsg.msgData.plaintext.contextName, v3_engine[index].contextName, 32);
						//memcpy(snmpmsg.msgData.plaintext.contextEngineID, v3_engine[index].securityEngineID, 32);
						snmpmsg.msgSecurityParameters.msgAuthoritativeEngineTime= manager_engine.authInTime; //0x02a097;
						snmpmsg.msgSecurityParameters.msgAuthoritativeEngineBoots = manager_engine.boots;
						
						len = build_snmpmsg(msgin.msgContent, &snmpmsg, addr.remote_ip, addr.remote_port); 
						msgin.msgLength = len; 

						msgin.msgDstIP = addr.remote_ip; 
						msgin.msgDstPort = addr.remote_port; 
						msgin.msgSrcPort = addr.local_port; 
						snmp_logmsg(SNMPDB_OUT, &snmpmsg, &addr); 
						iptrPlatPutMessage(msgin); 
						continue;
					}
					else
					{//UltraVIEW OMC need a response
						snmpmsg.msgGlobalData.msgFlags &=1;
						snmpmsg.msgSecurityParameters.seqFlag |=1;						
						memcpy(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineID, manager_engine.securityEngineID, 32);
						snmpmsg.pdu_type = PDU_RSP;
						snmpmsg.var_num = 0;
						snmpmsg.error_status = 0x10;// authorizationError
						memcpy(&snmpmsg.var, &report_state, sizeof(var_list));
						snmpmsg.msgData.plaintext.seqFlag = 1;// contextEngineID						
						snmpmsg.msgSecurityParameters.msgAuthoritativeEngineTime= manager_engine.authInTime; //0x02a097;
						snmpmsg.msgSecurityParameters.msgAuthoritativeEngineBoots = manager_engine.boots;
						
						len = build_snmpmsg(msgin.msgContent, &snmpmsg, addr.remote_ip, addr.remote_port); 
						msgin.msgLength = len; 

						msgin.msgDstIP = addr.remote_ip; 
						msgin.msgDstPort = addr.remote_port; 
						msgin.msgSrcPort = addr.local_port; 
						snmp_logmsg(SNMPDB_OUT, &snmpmsg, &addr); 
						iptrPlatPutMessage(msgin); 
						continue;
					}
						
				}	

		}
		
		
		if(snmpmsg.msgVersion == SNMP_V3 && (snmpmsg.msgGlobalData.msgFlags&4)!=0 && err_status !=0)
		{//send report
			var_list report_state=
					{
						.oid={1,3,6,1,6,3,15,1,1,1,0},//{1,3,6,1,4,1,1373,2,3,2},//PLATFORM_HB_OID,
						.oidlen=11,//PLATFORM_HB_LEN,
						.vartype=0x41,
						.msglen=1,
						.msg={1}				
					};
						report_state.oid[9]=err_status;
						snmpmsg.msgGlobalData.msgFlags &=1;
						snmpmsg.msgSecurityParameters.seqFlag |=1;
						//memcpy(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineID, securityEngineID, 32); //pierre
						//memcpy(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineID, v3_engine[index].securityEngineID, 32);
						snmpmsg.pdu_type = PDU_REPORT;
						snmpmsg.var_num = 1;
						//report_state.msglen = encode_integer(report_state.msg ,  manager_engine.authInTime);
						memcpy(&snmpmsg.var, &report_state, sizeof(var_list));
						snmpmsg.msgData.plaintext.seqFlag = 1;// contextEngineID
						//memcpy(snmpmsg.msgData.plaintext.contextEngineID, securityEngineID, 32); //pierre
						//memcpy(snmpmsg.msgData.plaintext.contextName, v3_engine[index].contextName, 32);
						//memcpy(snmpmsg.msgData.plaintext.contextEngineID, v3_engine[index].securityEngineID, 32);
						snmpmsg.msgSecurityParameters.msgAuthoritativeEngineTime= manager_engine.authInTime; //0x02a097;
						snmpmsg.msgSecurityParameters.msgAuthoritativeEngineBoots = manager_engine.boots;
						
						len = build_snmpmsg(msgin.msgContent, &snmpmsg, addr.remote_ip, addr.remote_port); 
						msgin.msgLength = len; 

						msgin.msgDstIP = addr.remote_ip; 
						msgin.msgDstPort = addr.remote_port; 
						msgin.msgSrcPort = addr.local_port; 
						snmp_logmsg(SNMPDB_OUT, &snmpmsg, &addr); 
						iptrPlatPutMessage(msgin); 
						continue;

		}
		if(snmpmsg.msgVersion == SNMP_V3 && (snmpmsg.pdu_type==PDU_GETNEXT))
		{//send report
			var_list report_state=
			{
				.oid={1,3,6,1,2,1,1,3},//{1,3,6,1,4,1,1373,2,3,2},//PLATFORM_HB_OID,
				.oidlen=8,//PLATFORM_HB_LEN,
				.vartype=0x43,
				.msglen=3,
				.msg={0xf5}				
			};
			if(memcmp(report_state.oid ,snmpmsg.var[0].oid, 8*4)==0)
			{
					snmpmsg.msgSecurityParameters.seqFlag |=1;
					//memcpy(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineID, securityEngineID, 32); //pierre
					//memcpy(snmpmsg.msgSecurityParameters.msgAuthoritativeEngineID, v3_engine[index].securityEngineID, 32);
					snmpmsg.pdu_type = PDU_RSP;
					snmpmsg.var_num = 1;
					report_state.msglen = encode_integer(report_state.msg ,  manager_engine.authInTime*100);
					memcpy(&snmpmsg.var, &report_state, sizeof(var_list));
					snmpmsg.msgData.plaintext.seqFlag = 1;// contextEngineID
					//memcpy(snmpmsg.msgData.plaintext.contextEngineID, securityEngineID, 32); //pierre
					//memcpy(snmpmsg.msgData.plaintext.contextName, v3_engine[index].contextName, 32);
					//memcpy(snmpmsg.msgData.plaintext.contextEngineID, v3_engine[index].securityEngineID, 32);
					snmpmsg.msgSecurityParameters.msgAuthoritativeEngineTime= manager_engine.authInTime; //0x02a097;
					snmpmsg.msgSecurityParameters.msgAuthoritativeEngineBoots = manager_engine.boots;
					len = build_snmpmsg(msgin.msgContent, &snmpmsg, addr.remote_ip, addr.remote_port); 
					msgin.msgLength = len; 

					msgin.msgDstIP = addr.remote_ip; 
					msgin.msgDstPort = addr.remote_port; 
					msgin.msgSrcPort = addr.local_port; 
					snmp_logmsg(SNMPDB_OUT, &snmpmsg, &addr); 
					iptrPlatPutMessage(msgin); 
					continue;

			}

		}
		
		switch(snmpmsg.pdu_type)
		{
		case PDU_RSP:
			pCsta->rsp_in++; 
			rsp_handle(snmpmsg.var[0].oidlen, snmpmsg.var[0].oid, &snmpmsg, &addr); 
			continue; 
			break;
		case PDU_SET:
			pCsta->set_in++; 
			if(snmpmsg.error_status != 0 )
				continue; 
			if(snmp_handle(snmpmsg.var[0].oidlen, snmpmsg.var[0].oid, &snmpmsg, &addr)>0)
				continue; 
			break; 
		case PDU_GET:
			pCsta->get_in++; 
			if(snmpmsg.error_status != 0 )
				continue; 
			if(snmp_handle(snmpmsg.var[0].oidlen, snmpmsg.var[0].oid, &snmpmsg, &addr)>0)
				continue; 
			break; 
		case PDU_TRAP:
			pCsta->trap_in++; 
			break; 
		case PDU_GETNEXT:
			//add by yizane start
			pCsta->getnext_in++; 
			if(snmpmsg.error_status != 0 )
				continue; 
			if(snmp_handle(snmpmsg.var[0].oidlen, snmpmsg.var[0].oid, &snmpmsg, &addr)>0)
				continue; 			
			break; 
		case PDU_GETBULK:
			pCsta->getbulk_in++;
			if(snmpmsg.error_status != 0 )
				continue; 			
			if(snmp_handle(snmpmsg.var[0].oidlen, snmpmsg.var[0].oid, &snmpmsg, &addr)>0)
				continue;
			break;
			//add by yizane end
		case PDU_REPORT:
			if(snmpmsg.msgVersion==SNMP_V3 && snmpVersion==SNMP_V3)
					{
						int index=0, ret;
						DWORD authInTimeOid[]={1,3,6,1,6,3,15,1,1,2};
						DWORD unknowEngineOid[]={1,3,6,1,6,3,15,1,1,4};
						int oidlen=10;

						ret = memcmp(poid,unknowEngineOid, oidlen*4);
						if(memcmp(poid,authInTimeOid, oidlen*4)==0||ret==0)
						{
							index = find_engine_server(snmpmsg.msgSecurityParameters.msgUserName, addr.remote_ip);
							if(!strcmp(snmpmsg.msgSecurityParameters.msgUserName, v3_engine[index].securityUserName))
							{
								v3_engine[index].authInTime = snmpmsg.msgSecurityParameters.msgAuthoritativeEngineTime;
								v3_engine[index].boots = snmpmsg.msgSecurityParameters.msgAuthoritativeEngineBoots;
								memcpy(v3_engine[index].contextEngineID,snmpmsg.msgData.plaintext.contextEngineID,0x0c);
							}
						}
					}
			continue;
			break;
		default:
			snmp_debug(SNMPDB_ERR, "Unknow PDU type(%d)!", snmpmsg.pdu_type); 
			snmp_logmsg(SNMPDB_ERR, &snmpmsg, &addr); 
			continue; 
		}

		//deal with each variable in var_list
		for(i = 0; i < snmpmsg.var_num; i++)
		{
			pvar = &snmpmsg.var[i]; 
			poid = pvar->oid; 
			idlen = pvar->oidlen; 
			switch(snmpmsg.pdu_type)
			{
			case PDU_TRAP:
				if(trap_handle(idlen, poid, pvar->msg, pvar->msglen, &addr) == 1)
					continue; 
				for(j = 0; j < fun_num; j++)
				{
					if(trap_proc[j] != NULL)
						trap_proc[j](idlen, poid, pvar->msg, pvar->msglen, &addr); 
				}
				continue; 
			case PDU_GETNEXT:
				//add by yizane start
				memset(in_oid,0,OID_MAXLEN*sizeof(DWORD));
				memcpy(in_oid,poid,idlen*sizeof(DWORD));
				len = getnext_response(idlen, in_oid, &pvar->oidlen, poid, pvar->msg, &pvar->vartype);				
				if(len >= 0){
					pvar->msglen = len; 					//L
				}	
				else if(len == -1)
				{
					snmp_debug(SNMPDB_NOREG, "EndOfMibView"); 
					snmp_logmsg(SNMPDB_NOREG, &snmpmsg, &addr); 
					pvar->vartype = EndOfMibView; 
					pvar->msglen = 0; 					
				}
				else
				{
					snmpmsg.error_status=3;
					snmpmsg.error_index = i + 1;
					pvar->vartype = 4;
					pvar->msg[128] = 0;
					pvar->msglen = strlen((char *)pvar->msg);
				}
				break; 							
				//add by yizane end

			case PDU_GET:
				len = get_response(idlen, poid, pvar->msg, &pvar->vartype); 
				
				if(len >= 0)
					pvar->msglen = len; 					//L
				else if(len == -1)
				{
					snmp_debug(SNMPDB_NOREG, "NoSuchObject or NoSuchInstance:"); 
					snmp_logmsg(SNMPDB_NOREG, &snmpmsg, &addr); 
					if(poid[idlen-1] == 0)
						pvar->vartype = NoSuchObject; 
					else
						pvar->vartype = NosuchInstance; 
					pvar->msglen = 0; 
				}
				else
				{
					snmpmsg.error_status=3;
					snmpmsg.error_index = i + 1;
					pvar->vartype = 4;
					pvar->msg[128] = 0;
					pvar->msglen = strlen((char *)pvar->msg);
				}
				break; 
			case PDU_SET:
				len = set_response(idlen, poid, pvar->msg, pvar->msglen); 
				if(len >= 0)
				{
					pvar->msglen = len; 					//L
				}
				else if(len == -1)
				{
					snmp_debug(SNMPDB_NOREG, "NoSuchObject or NoSuchInstance:"); 
					snmp_logmsg(SNMPDB_NOREG, &snmpmsg, &addr); 
					if(poid[idlen-1] == 0)
						pvar->vartype = NoSuchObject; 
					else
						pvar->vartype = NosuchInstance; 
					pvar->msglen = 0; 
				}
				else
				{
					snmpmsg.error_status=3;
					snmpmsg.error_index = i + 1;
					pvar->vartype = 4;
					pvar->msg[128] = 0;
					pvar->msglen = strlen((char *)pvar->msg);
				}
				break; 
			case PDU_REPORT:
					break;
			}/* switch */
		} /* for */
		
//add  by yizane start
		if(snmpmsg.pdu_type == PDU_GETBULK){
			int n,m,r,end_count,index;
			static DWORD			*pre_poid; 
			m = snmpmsg.max_repetitions;			
			
	    if (snmpmsg.non_repeaters < snmpmsg.var_num) {
	        n = snmpmsg.non_repeaters;
	    } else {
	        n = snmpmsg.var_num;
	    }
	    if ((r = snmpmsg.var_num - n) < 0) {
	        r = 0;
	    }			
			
			snmpmsg.var_num=0;
			for(i = 0; i < n; i++){	
				if(i>=BIND_MAX){	
					break;
				}		
				pvar = &snmpmsg.var[i]; 
				poid = pvar->oid; 
				idlen = pvar->oidlen; 				
				
				memset(in_oid,0,OID_MAXLEN*sizeof(DWORD));
				memcpy(in_oid,poid,idlen*sizeof(DWORD));
				len = getnext_response(idlen, in_oid, &pvar->oidlen, poid, pvar->msg, &pvar->vartype);				
				if(len >= 0)
					pvar->msglen = len; 					//L
				else if(len == -1)
				{
					snmp_debug(SNMPDB_NOREG, "EndOfMibView"); 
					snmp_logmsg(SNMPDB_NOREG, &snmpmsg, &addr); 
					pvar->vartype = EndOfMibView; 
					pvar->msglen = 0; 
				}
				else
				{
					snmpmsg.error_status=3;
					snmpmsg.error_index = i + 1;
					pvar->vartype = 4;
					pvar->msg[128] = 0;
					pvar->msglen = strlen((char *)pvar->msg);
				}						
				snmpmsg.var_num++;
			}
			

			
			for(i = 0; i < m; i++){		
				end_count=0;		
				for(j = 0; j < r; j++){					
					index = n+i*r+j;
					if(index>=BIND_MAX){
						end_count = r ;						
						break;
					}
					pvar = &snmpmsg.var[index]; 
					poid = pvar->oid; 
					
					memset(in_oid,0,OID_MAXLEN*sizeof(DWORD));
					if(i==0)
					{
						pre_poid = pvar->oid; 
						idlen 	 = pvar->oidlen; 		
						memcpy(in_oid,pre_poid,idlen*sizeof(DWORD));												
					}
					else
					{
						pre_poid = snmpmsg.var[n+i*r+j-r].oid; 
						idlen = snmpmsg.var[n+i*r+j-r].oidlen; 								
						memcpy(in_oid,pre_poid,idlen*sizeof(DWORD));						
					}										
					
					len = getnext_response(idlen, in_oid, &pvar->oidlen, poid, pvar->msg, &pvar->vartype);				
					if(len >= 0)
						pvar->msglen = len; 					//L
					else if(len == -1)
					{
						snmp_debug(SNMPDB_NOREG, "EndOfMibView"); 
						snmp_logmsg(SNMPDB_NOREG, &snmpmsg, &addr); 
						pvar->vartype = EndOfMibView; 
						pvar->msglen = 0; 
						end_count++;
					}
					else
					{
						snmpmsg.error_index = i + 1;
						pvar->vartype = 4;
						pvar->msg[128] = 0;
						pvar->msglen = strlen((char *)pvar->msg);
					}											
					snmpmsg.var_num++;

				}					
				if(end_count==r)
					break;			
			}
			
			if(snmpmsg.var_num>BIND_MAX)
				snmpmsg.var_num=BIND_MAX;
		}
		
		//response---------------->
		//response---------------->
		if(snmpmsg.pdu_type == PDU_SET || snmpmsg.pdu_type == PDU_GET
		|| snmpmsg.pdu_type == PDU_GETNEXT|| snmpmsg.pdu_type == PDU_GETBULK )
//add  by yizane end		
		{
			snmpmsg.pdu_type = PDU_RSP;
			/*
			if(len != -2)
			{
				snmpmsg.error_index = 0;
			}
			*/
			/*
			if(len == -2)
			{
				snmpmsg.error_status = 3;
				snmpmsg.error_index = 1;
			}
			else
			{
				snmpmsg.error_index = 0;
			}
			*/
			len = build_snmpmsg(msgin.msgContent, &snmpmsg, addr.remote_ip, addr.remote_port); 
			msgin.msgLength = len; 

			msgin.msgDstIP = addr.remote_ip; 
			msgin.msgDstPort = addr.remote_port; 
			msgin.msgSrcPort = addr.local_port; 
			snmp_logmsg(SNMPDB_OUT, &snmpmsg, &addr); 
			iptrPlatPutMessage(msgin); 
		}
	}

}

int get_response(BYTE oidlen, DWORD *oid, BYTE *pdata, BYTE *vartype)
{
	BYTE		i = 0; 
	mib_nod		*p1; 

#if SNMP_DEBUG_LOG
	char	debugBuf[512];
	sprintf(debugBuf,
	"get_response(), oidlen: %d, lastest 8 oid:%ld.%ld.%ld.%ld.%ld.%ld.%ld.%ld",
		oidlen,oid[oidlen-9],
		oid[oidlen-8],oid[oidlen-7],oid[oidlen-6],oid[oidlen-5],
		oid[oidlen-4],oid[oidlen-3],oid[oidlen-2]);
	snmpLogInfo(debugBuf);
#endif

	p1 = phead; 
	while(i < oidlen)
	{
		if(p1 == NULL)
		{
			pCsta->not_register++; 
			return -1; 
		}
		if(p1->id == oid[i])
		{
			if(p1->get_proc != NULL)
				return p1->get_proc(oidlen, oid, pdata, vartype); 
			if(i<oidlen-1)
				p1 = p1->psub; 
		}
		else
		{
			if(p1->pnext == NULL)
			{
				pCsta->not_register++; 
				return -1; 
			}
			else
			{
				p1 = p1->pnext; 
				continue; 
			}
		}
		i++; 
	}
	pCsta->not_register++; 
	return -1; 
}

//add by yizane start
int	getnext_response(BYTE in_oidlen, DWORD *in_oid, BYTE *oidlen, DWORD *oid, BYTE *pdata,BYTE *vartype)
{
	BYTE		i = 0; 
	mib_nod		*p1; 
	p1 = phead; 
	
	while(i < in_oidlen)
	{
		if(p1 == NULL)
		{
			pCsta->not_register++; 
			return -1; 
		}
		if(p1->id == in_oid[i])
		{
			if(p1->getnext_proc != NULL)
				return p1->getnext_proc(in_oidlen, in_oid, oidlen, oid, pdata, vartype); 
			if(i<in_oidlen-1)
				p1 = p1->psub; 
		}
		else
		{
			if(p1->pnext == NULL)
			{
				pCsta->not_register++; 
				return -1; 
			}
			else
			{
				p1 = p1->pnext; 
				continue; 
			}
		}
		i++; 
	}
	pCsta->not_register++; 
	return -1; 
}
//add by yizane end

int set_response(BYTE oidlen, DWORD *oid, BYTE *pdata, WORD datalen)
{
	BYTE		i = 0; 
	mib_nod		*p1; 
	
#if SNMP_DEBUG_LOG
	char		debugBuf[512];
	sprintf(debugBuf,
	"set_response(), oidlen: %d, lastest 8 oid:%ld.%ld.%ld.%ld.%ld.%ld.%ld.%ld",
		oidlen,oid[oidlen-9],
		oid[oidlen-8],oid[oidlen-7],oid[oidlen-6],oid[oidlen-5],
		oid[oidlen-4],oid[oidlen-3],oid[oidlen-2]);
	snmpLogInfo(debugBuf);
#endif
	p1 = phead; 
	while(i < oidlen)
	{
		if(p1 == NULL)
		{
			pCsta->not_register++; 
			return -1; 
		}
		if(p1->id == oid[i])
		{
			if(p1->set_proc != NULL)
				return p1->set_proc(oidlen, oid, pdata, datalen); 
			if(i < oidlen-1)
				p1 = p1->psub; 
		}
		else
		{
			if(p1->pnext == NULL)
			{
				pCsta->not_register++; 
				return -1; 
			}
			else
			{
				p1 = p1->pnext; 
				continue; 
			}
		}
		i++; 
	}
	pCsta->not_register++; 
	return -1; 
}

int trap_handle(BYTE oidlen, DWORD *oid, BYTE *pdata, WORD datalen, snmp_addr *addr)
{
	BYTE		i = 0; 
	mib_nod		*p1; 
	
#if SNMP_DEBUG_LOG
	char		debugBuf[512];
	sprintf(debugBuf,
	"trap_handle(), oidlen: %d, lastest 8 oid:%ld.%ld.%ld.%ld.%ld.%ld.%ld.%ld",
		oidlen,oid[oidlen-9],
		oid[oidlen-8],oid[oidlen-7],oid[oidlen-6],oid[oidlen-5],
		oid[oidlen-4],oid[oidlen-3],oid[oidlen-2]);
	snmpLogInfo(debugBuf);
#endif
	
	p1 = phead; 
	while(i < oidlen)
	{
		if(p1 == NULL)
			return -1; 
		if(p1->id == oid[i])
		{
			if(p1->trap_proc != NULL)
			{
				p1->trap_proc(oidlen, oid, pdata, datalen, addr); 
				return 1; 
			}
			if(i < oidlen-1)
				p1 = p1->psub; 
		}
		else
		{
			if(p1->pnext == NULL)
				return -1; 
			else
			{
				p1 = p1->pnext; 
				continue; 
			}
		}
		i++; 
	}
	return -1; 
}

int rsp_handle(BYTE oidlen, DWORD *oid, snmp_pdu *pdu, snmp_addr *addr)
{
	BYTE		i = 0; 
	mib_nod		*p1; 
	
#if SNMP_DEBUG_LOG
	char		debugBuf[512];
	sprintf(debugBuf,
	"rsp_handle(), oidlen: %d, lastest 8 oid:%ld.%ld.%ld.%ld.%ld.%ld.%ld.%ld",
		oidlen,oid[oidlen-9],
		oid[oidlen-8],oid[oidlen-7],oid[oidlen-6],oid[oidlen-5],
		oid[oidlen-4],oid[oidlen-3],oid[oidlen-2]);
	snmpLogInfo(debugBuf);
#endif
	
	p1 = phead; 
	while(i < oidlen)
	{
		if(p1 == NULL)
		{
			pCsta->not_register++; 
			return -1; 
		}
		if(p1->id == oid[i])
		{
			if(p1->rsp_proc != NULL)
			{
				p1->rsp_proc(pdu, addr); 
				return 1; 
			}
			if(i < oidlen-1)
				p1 = p1->psub; 
		}
		else
		{
			if(p1->pnext == NULL)
			{
				pCsta->not_register++; 
				return -1; 
			}
			else
			{
				p1 = p1->pnext; 
				continue; 
			}
		}
		i++; 
	}
	pCsta->not_register++; 
	return -1; 
}

int snmp_handle(BYTE oidlen, DWORD *oid, snmp_pdu *pdu, snmp_addr *addr)
{
	BYTE		i = 0; 
	mib_nod		*p1; 
	
#if SNMP_DEBUG_LOG
	char		debugBuf[512];
	sprintf(debugBuf,
	"snmp_handle(), oidlen: %d, lastest 8 oid:%ld.%ld.%ld.%ld.%ld.%ld.%ld.%ld",
		oidlen,oid[oidlen-9],
		oid[oidlen-8],oid[oidlen-7],oid[oidlen-6],oid[oidlen-5],
		oid[oidlen-4],oid[oidlen-3],oid[oidlen-2]);
	snmpLogInfo(debugBuf);
#endif

	p1 = phead; 
	while(i < oidlen)
	{
		if(p1 == NULL)
			return -1; 
		if(p1->id == oid[i])
		{
			if(p1->snmp_proc != NULL)
			{
				p1->snmp_proc(pdu, addr); 
				return 1; 
			}
			if(i < oidlen-1)
				p1 = p1->psub; 
		}
		else
		{
			if(p1->pnext == NULL)
				return -1; 
			else
			{
				p1 = p1->pnext; 
				continue; 
			}
		}
		i++; 
	}
	return -1; 
}

void snmp_hb_init()
{
	BYTE	status[64] = {3, 3, 2, 1}; 
	status[4] = trapcall_num; 
	status[5] = setcall_num; 
	status[6] = getcall_num; 
	status[7] = rspcall_num; 
	set_status(4, 8, status); 
}
/********************************************************************/

void inquire_trapmsg(trapcall func)
{
	BYTE	i; 
	for(i = 0; i < fun_num && i < 100; i++)
	{
		if(trap_proc[i] == NULL)
		{
			trap_proc[i] = func; 
			fun_num = i+1; 
			return; 
		}
		if(trap_proc[i] == func)
			return; 
	}
	if(fun_num >= 100)
		return; 
	trap_proc[fun_num++] = func; 
	trapcall_num++; 
	snmp_hb_init(); 
}

void rob_trapmsg(BYTE oidlen, DWORD *oid, trapcall trap_proc)
{
	BYTE			i = 0; 
	mib_nod			*p1, *p2; 
	if(phead == NULL)
	{
		phead = (mib_nod *)getmem(sizeof(mib_nod)); 
		phead->id = oid[0]; 
	}
	p1 = phead; 
	while(i < oidlen)
	{
		if(p1->id == oid[i])
		{
			if(i == oidlen-1)	
				p1->trap_proc = trap_proc; 
			else			
			{
				if(p1->psub == NULL)
				{
					p2 = (mib_nod *)getmem(sizeof(mib_nod)); 				
					p2->id = oid[i+1]; 
					p1->psub = p2; 
					p1 = p2; 
				}
				else
					p1 = p1->psub; 
			}
		}
		else				
		{
			if(p1->pnext == NULL)
			{
				p2 = (mib_nod *)getmem(sizeof(mib_nod)); 
				p2->id = oid[i]; 
				p1->pnext = p2; 
				p1 = p2; 
			}
			else
				p1 = p1->pnext; 
			continue; 
		}
		i++; 
	}
	trapcall_num++; 
	snmp_hb_init(); 
}

void inquire_setmsg(BYTE oidlen, DWORD *oid, setcall set_proc)
{
	BYTE			i = 0; 
	mib_nod			*p1, *p2; 
	if(phead == NULL)
	{
		phead = (mib_nod *)getmem(sizeof(mib_nod)); 
		phead->id = oid[0]; 
	}
	p1 = phead; 
	while(i < oidlen)
	{
		if(p1->id == oid[i])
		{
			if(i == oidlen-1)	
				p1->set_proc = set_proc; 
			else			
			{
				if(p1->psub == NULL)
				{
					p2 = (mib_nod *)getmem(sizeof(mib_nod)); 				
					p2->id = oid[i+1]; 
					p1->psub = p2; 
					p1 = p2; 
				}
				else
					p1 = p1->psub; 
			}
		}
		else				
		{
			if(p1->pnext == NULL)
			{
				p2 = (mib_nod *)getmem(sizeof(mib_nod)); 
				p2->id = oid[i]; 
				p1->pnext = p2; 
				p1 = p2; 
			}
			else
				p1 = p1->pnext; 
			continue; 
		}
		i++; 
	}
	setcall_num++; 
	snmp_hb_init(); 
}

void inquire_getmsg(BYTE oidlen, DWORD *oid, getcall get_proc)
{
	BYTE			i = 0; 
	mib_nod			*p1, *p2; 
	if(phead == NULL)
	{
		phead = (mib_nod *)getmem(sizeof(mib_nod)); 
		phead->id = oid[0]; 
	}
	p1 = phead; 
	while(i < oidlen)
	{
		if(p1->id == oid[i])
		{
			if(i == oidlen - 1)	
				p1->get_proc = get_proc; 
			else			
			{
				if(p1->psub == NULL)
				{
					p2 = (mib_nod *)getmem(sizeof(mib_nod)); 				
					p2->id = oid[i+1]; 
					p1->psub = p2; 
					p1 = p2; 
				}
				else
					p1 = p1->psub; 
			}
		}
		else				
		{
			if(p1->pnext == NULL)
			{
				p2 = (mib_nod *)getmem(sizeof(mib_nod)); 
				p2->id = oid[i]; 
				p1->pnext = p2; 
				p1 = p2; 
			}
			else
				p1 = p1->pnext; 
			continue; 
		}
		i++; 
	}
	getcall_num++; 
	snmp_hb_init(); 
}

//add by yizane start
void inquire_getnextmsg(BYTE oidlen, DWORD *oid, getnextcall getnext_proc)
{
	BYTE			i = 0; 
	mib_nod			*p1, *p2; 
	if(phead == NULL)
	{
		phead = (mib_nod *)getmem(sizeof(mib_nod)); 
		phead->id = oid[0]; 
	}
	p1 = phead; 
	while(i < oidlen)
	{
		if(p1->id == oid[i])
		{
			if(i == oidlen - 1)	
				p1->getnext_proc = getnext_proc; 
			else			
			{
				if(p1->psub == NULL)
				{
					p2 = (mib_nod *)getmem(sizeof(mib_nod)); 				
					p2->id = oid[i+1]; 
					p1->psub = p2; 
					p1 = p2; 
				}
				else
					p1 = p1->psub; 
			}
		}
		else				
		{
			if(p1->pnext == NULL)
			{
				p2 = (mib_nod *)getmem(sizeof(mib_nod)); 
				p2->id = oid[i]; 
				p1->pnext = p2; 
				p1 = p2; 
			}
			else
				p1 = p1->pnext; 
			continue; 
		}
		i++; 
	}
	getcall_num++; 
	snmp_hb_init(); 
}
//add by yizane end

void inquire_rspmsg(BYTE oidlen, DWORD *oid, rspcall rsp_proc)
{
	
	BYTE			i = 0; 
	mib_nod			*p1, *p2; 
	if(phead == NULL)
	{
		phead = (mib_nod *)getmem(sizeof(mib_nod)); 
		phead->id = oid[0]; 
	}
	p1 = phead; 
	while(i<oidlen)
	{
		if(p1->id == oid[i])
		{
			if(i == oidlen - 1)	
				p1->rsp_proc = rsp_proc; 
			else			
			{
				if(p1->psub == NULL)
				{
					p2 = (mib_nod *)getmem(sizeof(mib_nod)); 				
					p2->id = oid[i+1]; 
					p1->psub = p2; 
					p1 = p2; 
				}
				else
					p1 = p1->psub; 
			}
		}
		else				
		{
			if(p1->pnext == NULL)
			{
				p2 = (mib_nod *)getmem(sizeof(mib_nod)); 
				p2->id = oid[i]; 
				p1->pnext = p2; 
				p1 = p2; 
			}
			else
				p1 = p1->pnext; 
			continue; 
		}
		i++; 
	}
	rspcall_num++; 
	snmp_hb_init(); 
}

void inquire_snmpmsg(BYTE oidlen, DWORD *oid, snmpcall snmp_proc)
{
	
	BYTE		i = 0; 
	mib_nod			*p1, *p2; 
	if(phead == NULL)
	{
		phead = (mib_nod *)getmem(sizeof(mib_nod)); 
		phead->id = oid[0]; 
	}
	p1 = phead; 
	while(i < oidlen)
	{
		if(p1->id == oid[i])
		{
			if(i == oidlen-1)	
				p1->snmp_proc = snmp_proc; 
			else			
			{
				if(p1->psub == NULL)
				{
					p2 = (mib_nod *)getmem(sizeof(mib_nod)); 				
					p2->id = oid[i+1]; 
					p1->psub = p2; 
					p1 = p2; 
				}
				else
					p1 = p1->psub; 
			}
		}
		else				
		{
			if(p1->pnext == NULL)
			{
				p2 = (mib_nod *)getmem(sizeof(mib_nod)); 
				p2->id = oid[i]; 
				p1->pnext = p2; 
				p1 = p2; 
			}
			else
				p1 = p1->pnext; 
			continue; 
		}
		i++; 
	}
	//rspcall_num++; 
	//snmp_hb_init(); 
}
/********************************************************************/

int snmp_send(snmp_pdu *msgbuf, snmp_addr *addr)
{
	message_list		msgout; 
	
#if SNMP_DEBUG_LOG
	char		debugBuf[512];
#endif	
	snmp_logmsg(SNMPDB_OUT, msgbuf, addr); 
	if(msgbuf->var_num == 0 || msgbuf->var_num >BIND_MAX)
	{
		snmp_debug(SNMPDB_ERR, "var_num = %d, exceed limit(%d)", msgbuf->var_num, BIND_MAX); 
		snmp_logmsg(SNMPDB_ERR, msgbuf, addr); 
		return 0; 
	}

#if SNMP_DEBUG_LOG
	sprintf(debugBuf,"snmp_send() pdu_type: %d",msgbuf->pdu_type);
	snmpLogInfo(debugBuf);
#endif

	switch(msgbuf->pdu_type)
	{
	case PDU_SET:
		pCsta->set_out++; 
		msgbuf->error_index = msgbuf->error_status = 0; 
		if(msgbuf->request_id == 0  )
			msgbuf->request_id = assign_rid(); 
		break; 
	case PDU_GET:
		pCsta->get_out++; 
		msgbuf->error_index = msgbuf->error_status = 0; 
		if(msgbuf->request_id == 0  )
			msgbuf->request_id = assign_rid(); 
		break; 
	//add by yizane start	
	case PDU_GETNEXT:		
		pCsta->getnext_out++; 
		msgbuf->error_index = msgbuf->error_status = 0; 
		if(msgbuf->request_id == 0  )
			msgbuf->request_id = assign_rid(); 
		break; 		
	case PDU_GETBULK:
		pCsta->getbulk_out++; 
		msgbuf->error_index = msgbuf->error_status = 0; 
		if(msgbuf->request_id == 0  )
			msgbuf->request_id = assign_rid(); 
		break; 				
	//add by yizane end	
	case PDU_TRAP:
		pCsta->trap_out++; 
		msgbuf->request_id = 1; 

#ifdef	_EWS_H_	
		if(addr->local_port == 4957 && addr->remote_port == 4957)
		{
			ews_proc_heartbeat(msgbuf->var[0].oidlen,
								msgbuf->var[0].oid,
								msgbuf->var[0].msglen,
								msgbuf->var[0].msg);
		}
#endif		
		break; 
	case PDU_RSP:
		pCsta->rsp_out++; 
		break; 
	default:
		return 0; 
	}
#if SNMP_DEBUG_LOG	
	sprintf(debugBuf,"snmp_send->msginfo: %08lx.%04d to %08lx.%04d",
		addr->local_ip,addr->local_port,
		addr->remote_ip,addr->remote_port);
	snmpLogInfo(debugBuf);
#endif

	msgout.msgLength = build_snmpmsg(msgout.msgContent , msgbuf, addr->remote_ip, addr->remote_port); 
	if(msgout.msgLength == 0 || msgout.msgLength > 1500)
	{
		snmp_debug(SNMPDB_ERR, "Encoding Failure or Message length exceed limit"); 
		snmp_logmsg(SNMPDB_ERR, msgbuf, addr); 
		return 0; 
	}

	msgout.msgDstIP = addr->remote_ip ; 
	msgout.msgDstPort  = addr->remote_port ; 
	msgout.msgSrcIP = addr->local_ip ; 
	msgout.msgSrcPort = addr->local_port ; 
	msgout.msgBroadcast = addr->broadcast ; 

#if SNMP_DEBUG_LOG
	snmpLogInfo("end of snmp_send()");
#endif
	if(iptrPutMessage(msgout) == 0)
		return 0; 
	else
		return msgbuf->request_id; 
}

int snmp_plat_send(snmp_pdu *msgbuf, snmp_addr *addr)
{
	message_list		msgout; 

	snmp_logmsg(SNMPDB_OUT, msgbuf, addr); 
	if(msgbuf->var_num == 0 || msgbuf->var_num >BIND_MAX)
	{
		snmp_debug(SNMPDB_ERR, "var_num = %d, exceed limit(%d)", msgbuf->var_num, BIND_MAX); 
		snmp_logmsg(SNMPDB_ERR, msgbuf, addr); 
		return 0; 
	}

	switch(msgbuf->pdu_type)
	{
	case PDU_SET:
		pCsta->set_out++; 
		msgbuf->error_index = msgbuf->error_status = 0; 
		if(msgbuf->request_id == 0  )
			msgbuf->request_id = assign_rid(); 
		break; 
	case PDU_GET:
		pCsta->get_out++; 
		msgbuf->error_index = msgbuf->error_status = 0; 
		if(msgbuf->request_id == 0  )
			msgbuf->request_id = assign_rid(); 
		break; 
	//add by yizane start	
	case PDU_GETNEXT:		
		pCsta->getnext_out++; 
		msgbuf->error_index = msgbuf->error_status = 0; 
		if(msgbuf->request_id == 0  )
			msgbuf->request_id = assign_rid(); 
		break; 		
	case PDU_GETBULK:
		pCsta->getbulk_out++; 
		msgbuf->error_index = msgbuf->error_status = 0; 
		if(msgbuf->request_id == 0  )
			msgbuf->request_id = assign_rid(); 
		break; 				
	//add by yizane end		
	case PDU_TRAP:
		pCsta->trap_out++; 
		msgbuf->request_id = 1; 
#ifdef	_EWS_H_	
		if(addr->local_port == 4957 && addr->remote_port == 4957)
		{
			ews_proc_heartbeat(msgbuf->var[0].oidlen,
								msgbuf->var[0].oid,
								msgbuf->var[0].msglen,
								msgbuf->var[0].msg);
		}
#endif				  
		break; 
	case PDU_RSP:
		pCsta->rsp_out++; 
		break; 
	default:
		return 0; 
	}
	
	msgout.msgLength = build_snmpmsg(msgout.msgContent , msgbuf, addr->remote_ip, addr->remote_port); 
	if(msgout.msgLength == 0 || msgout.msgLength > 1500)
	{
		snmp_debug(SNMPDB_ERR, "Encoding Failure or Messages length exceed limit"); 
		snmp_logmsg(SNMPDB_ERR, msgbuf, addr); 
		return 0; 
	}

	msgout.msgDstIP = addr->remote_ip ; 
	msgout.msgDstPort  = addr->remote_port ; 
	msgout.msgSrcIP = addr->local_ip ; 
	msgout.msgSrcPort = addr->local_port ; 
	msgout.msgBroadcast = addr->broadcast ; 

	if(iptrPlatPutMessage(msgout) == 0)
		return 0; 
	else
		return msgbuf->request_id; 
}


int snmp_receive(snmp_pdu *msgbuf, snmp_addr *addr)
{
	message_list		msgin; 
#if SNMP_DEBUG_SNMP
	char		debugBuf[512];
#endif
	BYTE err_status=0;

	if(iptrGetMessage(&msgin, addr->local_port) == 1)
	{
#if SNMP_DEBUG_SNMP
		sprintf(debugBuf,"snmp_receive(),len=%d, %08x.%04d from %08x.%04d entering parse_shmpmsg()",
		msgin.msgLength,
		msgin.msgSrcIP,msgin.msgSrcPort,
		msgin.msgDstIP,msgin.msgDstPort);
		snmpLogInfo(debugBuf);
#endif
		if(parse_snmpmsg(msgin.msgContent, msgin.msgLength, msgbuf, &err_status) == 1 && msgbuf->var_num>0)
		{
				if(msgbuf->msgVersion==SNMP_V3 && snmpVersion==SNMP_V3 && msgbuf->pdu_type==PDU_REPORT)
					{
						int index=0, ret;
						DWORD authInTimeOid[]={1,3,6,1,6,3,15,1,1,2};
						DWORD unknowEngineOid[]={1,3,6,1,6,3,15,1,1,4};
						int oidlen=10;

						ret = memcmp(msgbuf->var[0].oid,unknowEngineOid, 4*oidlen);					
						if(memcmp(msgbuf->var[0].oid,authInTimeOid, 4*oidlen)==0 ||ret == 0)
						{
							index = find_engine_server(msgbuf->msgSecurityParameters.msgUserName,msgin.msgSrcIP);
							if(index>=0)
							{
								v3_engine[index].authInTime = msgbuf->msgSecurityParameters.msgAuthoritativeEngineTime;
								v3_engine[index].boots = msgbuf->msgSecurityParameters.msgAuthoritativeEngineBoots;
								memcpy(v3_engine[index].securityEngineID, msgbuf->msgSecurityParameters.msgAuthoritativeEngineID, 32);
								memcpy(v3_engine[index].contextEngineID, msgbuf->msgData.plaintext.contextEngineID, 32);
								memcpy(v3_engine[index].contextName, msgbuf->msgData.plaintext.contextName,32);
								init_engine(v3_engine[index].securityUserName);
							}
						}
					}
			addr->remote_ip = msgin.msgSrcIP; 
			addr->remote_port = msgin.msgSrcPort; 
			addr->local_port = msgin.msgDstPort; 
			addr->local_ip = msgin.msgDstIP; 

			snmp_logmsg(SNMPDB_IN, msgbuf, addr); 
			return 1; 
		}
		else
		{
			pCsta->fail_parse++; 
			snmp_debug(SNMPDB_ERR, "Fail to parse message2.Give up dealing with it!, src ip=%x, src port=%d, dst port=%d", msgin.msgSrcIP,msgin.msgSrcPort,msgin.msgDstPort); 
			snmp_showbuf(SNMPDB_ERR, msgin.msgContent, msgin.msgLength); 			
		}
	}
	return 0; 
}

/********************************************************************/

int build_snmpmsg(BYTE *pbuf, snmp_pdu *psnmp, DWORD ip, WORD port)
{
	BYTE		msg[2000], encryptBuf[2000]={0}; 
	short		pos = 1900, len, outlen2,pdu_pos=0; 
	var_list	*pvar; 
	BYTE		var_num; 
	BYTE		idlen; 
	DWORD		*poid, val; 
	short		stack[10]; 
	BYTE		pstack = 0; 
	BOOL		error_status = 0; 
	BYTE  tmp_int[4];
	BYTE *pAuthPara;
	int index;
	static DWORD boots=0;
	u16  outlen = 0;
	
#if SNMP_DEBUG_LOG
	char		debugBuf[512];
	sprintf(debugBuf,"build_snmpmsg(): var_num: %d",psnmp->var_num);
	snmpLogInfo(debugBuf);
#endif
	if(snmpVersion == SNMP_V3)
	{
		switch(psnmp->pdu_type)
		{
			case PDU_INFORM:
			case PDU_REPORT:
			case PDU_RSP:
				psnmp->msgGlobalData.msgFlags &=0x3;
				break;
			case PDU_TRAP:
				load_engine_para(psnmp, ip, port);
				psnmp->msgGlobalData.msgFlags &=0x3;
				break;
			default:
				load_engine_para(psnmp, ip, port);
				psnmp->msgGlobalData.msgFlags |=0x4;
				break;
		}
	}
	else 
				psnmp->msgGlobalData.msgFlags =0;
//	if(psnmp->msgVersion != SNMP_V3 && snmpVersion==SNMP_V3)
//		load_engine_para(psnmp);
	psnmp->msgGlobalData.msgMaxSize = SNMP_VAR_MAX;
	var_num = psnmp->var_num; 
	for(pstack = 0; pstack < 5; pstack++)
		stack[pstack] = pos; 			//push
	
	while(var_num-- >0)
	{
		stack[pstack++] = pos; 		//push
		pvar = &psnmp->var[var_num]; 
	//add by yizane start	
		if(psnmp->pdu_type == PDU_GET||
			 psnmp->pdu_type == PDU_GETBULK||
			 psnmp->pdu_type == PDU_GETNEXT)
	//add by yizane end		
		{
			pvar->vartype = 5; 
			pvar->msglen = 0; 
		}
		else
		{
			switch(pvar->vartype)
			{
			case 5:		//NULL
			case NoSuchObject:
			case NosuchInstance:
			case EndOfMibView:
				pvar->msglen = 0; 
			}
		}
		poid = pvar->oid; 
		//Value
		if(pvar->msglen>SNMP_VAR_MAX)
		{
			if(psnmp->error_status == 0)
			{
				psnmp->error_status = 1; 			//Too big
				psnmp->error_index = var_num; 
			}
			snmp_debug(SNMPDB_ERR, "Variable's length(%d) exceed limit:varindex = %d", pvar->msglen, SNMP_VAR_MAX, var_num); 
			pvar->msglen = 0; 
			error_status = 1; 
			return 0;
		}
		else if(((pos - pvar->msglen) < 500&&snmpVersion!=SNMP_V3)||((pos - pvar->msglen) < 586&&snmpVersion==SNMP_V3))
		{
			if(psnmp->error_status == 0)
			{
				psnmp->error_status = 1; 			//Too big
				psnmp->error_index = var_num; 
			}
			snmp_debug(SNMPDB_ERR, "Totol length(%d) exceed limit(1500):current varindex = %d", 1900-pos+pvar->msglen, var_num); 
			pstack--;
			pvar->msglen = 0; 
//			error_status = 1; 
//			return 0;
			break;
		}
		else if(pvar->msglen > 0)
		{
			memcpy(msg + pos - pvar->msglen + 1, pvar->msg, pvar->msglen); 	//V
		}
		pos -= pvar->msglen; 

		insert_length(msg, pos, pvar->msglen); 					//L
		msg[pos--] = pvar->vartype; 								//T
		//Object ID
		stack[pstack++] = pos; 		//push
		
		idlen = pvar->oidlen; 
		if(idlen >= OID_MAXLEN)
		{
//			snmp_debug(SNMPDB_ERR, "OID's Length(%d) is Invalid.", idlen); 
			return 0; 
		}

		while(idlen-- > 2)										//V
		{
			val = poid[idlen]; 
			if(val < 0x80)			//1byte
				*(msg + (pos--)) = val; 
			else if(val < 0x4000)	//2byte
			{
				*(msg + (pos--)) = val & 0x7F; 
				*(msg + (pos--)) = ((val & 0x3FFF) >> 7) | 0x80; 
			}
			else if(val < 0x200000)	//3byte
			{
				*(msg + (pos--)) = val & 0x7F; 
				*(msg + (pos--)) = ((val & 0x3FFF) >> 7) | 0x80; 
				*(msg + (pos--)) = (val >> 14) | 0x80; 
			}
			else if(val < 0x10000000)	//4byte
			{
				*(msg + (pos--)) = val & 0x7F; 
				*(msg + (pos--)) = ((val & 0x3FFF) >> 7) | 0x80; 
				*(msg + (pos--)) = ((val & 0x1FFFFF) >> 14) | 0x80; 
				*(msg + (pos--)) = (val >> 21) | 0x80; 
			}
			else					//5byte
			{
				*(msg+(pos--)) = val & 0x7F; 
				*(msg+(pos--)) = ((val & 0x3FFF) >> 7) | 0x80; 
				*(msg+(pos--)) = ((val & 0x1FFFFF) >> 14) | 0x80; 
				*(msg+(pos--)) = ((val & 0x0FFFFFFF) >> 21) | 0x80; 
				*(msg+(pos--)) = (val>>28) | 0x80; 
			}
		}
		if(poid[0] > 3 || (poid[0] < 3 && poid[1] >= 40))
		{
//			snmp_debug(SNMPDB_ERR, "Wrong oid, varindex = %d, oid = %ld.%ld...\n", var_num, poid[0], poid[1]); 
			return 0; 
		}
		*(msg + (pos--)) = poid[idlen] + poid[idlen - 1] * 40; 


		len = stack[--pstack] - pos; 	//pop
		insert_length(msg, pos, len); 								//L
		msg[pos--] = 0x06; 
		//Variable
		len = stack[--pstack] - pos; 	//pop
		insert_length(msg, pos, len); 		//L
		msg[pos--] = 0x30; 					//T
	}; 
	
	//Variable Binding
	len = stack[--pstack] - pos; 	//pop
	insert_length(msg, pos, len); 						//L
	msg[pos--] = 0x30; 									//T
	//add by yizane start
	if(psnmp->pdu_type == PDU_GETBULK)
	{
	//max-repeaters
	msg[pos--] = psnmp->max_repetitions; 					//V
	msg[pos--] = 1; 										//L
	msg[pos--] = 0x02; 									//T			
	//Non-repeaters
	msg[pos--] = psnmp->non_repeaters; 					//V
	msg[pos--] = 1; 										//L
	msg[pos--] = 0x02; 									//T
	}
	else
	{
	//error index
	msg[pos--] = psnmp->error_index; 					//V
	msg[pos--] = 1; 										//L
	msg[pos--] = 0x02; 									//T
	//error status
	msg[pos--] = psnmp->error_status ; 					//V
	msg[pos--] = 1; 										//L
	msg[pos--] = 0x02; 									//T
	}
	//add by yizane end
	//request-id
	enc_integer(msg, pos, psnmp->request_id); 			//V L
	msg[pos--] = 0x02; 									//T
	//PDU
	len = stack[--pstack] - pos; 	//pop
	insert_length(msg, pos, len); 							//L
	msg[pos--] = psnmp->pdu_type | 0xA0; 					//T

	if(snmpVersion == SNMP_V3)//(psnmp->msgVersion==SNMP_V3)
	{
		len = strlen(psnmp->msgData.plaintext.contextName); 

		memcpy(msg + pos - len + 1, (BYTE *)psnmp->msgData.plaintext.contextName, len); 			//V
		pos -= len; 
		msg[pos--] = len;
		msg[pos--] = 0x4;//T

		if(psnmp->msgData.plaintext.seqFlag&1)
			len = 12; 
		else 
			len = 0;
		//memcpy(msg + pos - len + 1, (BYTE *)psnmp->msgData.plaintext.contextEngineID, len); 			//V
		memcpy(msg + pos - len + 1, (BYTE *)psnmp->msgSecurityParameters.msgAuthoritativeEngineID,len); //pierre, should be contextEngineID
		pos -= len; 
		msg[pos--] = len;
		msg[pos--] = 0x4;//T

	   	pdu_pos = pos+1; 
//		len = stack[--pstack] - pos; 	//pop
		len =1900-pos;
		insert_length(msg, pos, len); 							//L
		if((psnmp->msgGlobalData.msgFlags&0x3)!=3)
			msg[pos--] = 	0x30;
		else 
		{
			msg[pos--] = 0x30;
			pdu_pos = pos+1; 
/*		   	pdu_pos = pos+1; //encrypt pdu
			len =1900-pos;
			insert_length(msg, pos, len); 							//L	
			msg[pos--] = 	0x4;
*/
		}
//		len = stack[--pstack] - pos; 	//pop
		len = 1900 - pos;
		if(psnmp->msgGlobalData.msgFlags&1)//auth
		{
			
			psnmp->msgSecurityParameters.seqFlag |=16;
			index = find_engine(psnmp->msgSecurityParameters.msgUserName)%MAX_ENGINE;
			
			if((psnmp->msgGlobalData.msgFlags>>1)&1)
			{
				int i;
				psnmp->msgSecurityParameters.seqFlag |=32;
				snmpV3EncryptData(v3_engine[index].privacyKey, AUTH_KEY_LEN,\
					&msg[pdu_pos], len, encryptBuf, &outlen,\
					(u8 *)psnmp->msgSecurityParameters.msgPrivacyParameters, (u16 *)&outlen2, boots);
				for(i = 0; i<outlen; i++)
				{
					msg[1900-i] = encryptBuf[outlen-i-1];
				}
				pos = 1900-outlen;
				insert_length(msg, pos, outlen);
				msg[pos--] = 0x4;
				
			}
		}
		else 
			psnmp->msgSecurityParameters.seqFlag = psnmp->msgSecurityParameters.seqFlag%16;
			
		//build_msgSecurityParameters
		outlen2 = pos;
		if((psnmp->msgSecurityParameters.seqFlag>>5)&1)
			len = 8; 
		else 
			len = 0;
		memcpy(msg + pos - len + 1, (BYTE *)psnmp->msgSecurityParameters.msgPrivacyParameters, len); 			//V
		pos -= len; 
		msg[pos--] = len;
		msg[pos--] = 0x4;//T
		if((psnmp->msgSecurityParameters.seqFlag>>4)&1)
			len = 12; 
		else 
			len = 0;
		pAuthPara = msg + pos - len + 1;
		memcpy(msg + pos - len + 1, (BYTE *)psnmp->msgSecurityParameters.msgAuthenticationParameters, len); 			//V
		pos -= len; 
		msg[pos--] = len;
		msg[pos--] = 0x4;//T
		if((psnmp->msgSecurityParameters.seqFlag>>3)&1)
			len = strlen(psnmp->msgSecurityParameters.msgUserName); 
		else 
			len = 0;
		memcpy(msg + pos - len + 1, (BYTE *)psnmp->msgSecurityParameters.msgUserName, len); 			//V
		pos -= len; 
		msg[pos--] = len;
		msg[pos--] = 0x4;//T
		if((psnmp->msgSecurityParameters.seqFlag>>2)&1)	
		{
			len = encode_integer(tmp_int , psnmp->msgSecurityParameters.msgAuthoritativeEngineTime);
			memcpy(msg + pos -len + 1, tmp_int, len); 
		}
		else 
			len = 0;

		pos -= len; 
		msg[pos--] = len;
		msg[pos--] = 0x2;//T

		if((psnmp->msgSecurityParameters.seqFlag>>1)&1)
		{	
			len = encode_integer(tmp_int , psnmp->msgSecurityParameters.msgAuthoritativeEngineBoots);
			memcpy(msg + pos -len + 1, tmp_int, len); 
		}
		else 
			len = 0;

		pos -= len; 
		msg[pos--] = len;
		msg[pos--] = 0x2;//T

		if((psnmp->msgSecurityParameters.seqFlag)&1)
			len = 12;
		else 
			len = 0;
		memcpy(msg + pos - len + 1, (BYTE *)psnmp->msgSecurityParameters.msgAuthoritativeEngineID, len); 			//V
		pos -= len; 
		msg[pos--] = len;
		msg[pos--] = 0x4;//T

		len = outlen2-pos;
		insert_length(msg, pos, len); 							//L
		msg[pos--] = 	0x30;
		len = outlen2-pos;
		insert_length(msg, pos, len); 							//L
		msg[pos--] = 	0x4;

		//build_msgGlobalData
		outlen2 = pos;
		
		len = encode_integer(tmp_int , psnmp->msgGlobalData.msgSecurityModel);
		memcpy(msg + pos -len + 1, tmp_int, len); 		
		pos -= len; 
		msg[pos--] = len;
		msg[pos--] = 0x2;//T

		len = 1;
/*
		switch(psnmp->pdu_type)
		{
			case PDU_TRAP:
			case PDU_INFORM:
			case	PDU_REPORT:
			case PDU_RSP:
				psnmp->msgGlobalData.msgFlags &=0x3;
				break;
			default:
				psnmp->msgGlobalData.msgFlags |=0x4;
				break;
		}
*/
		msg[pos] = psnmp->msgGlobalData.msgFlags;
		pos -= len; 
		msg[pos--] = len;
		msg[pos--] = 0x4;//T

		if((psnmp->msgGlobalData.seqFlag>>1)&1)
		{
			len = encode_integer(tmp_int , psnmp->msgGlobalData.msgMaxSize);
			memcpy(msg + pos -len + 1, tmp_int, len); 
		}
		else 
			len = 0;

		pos -= len; 
		msg[pos--] = len;
		msg[pos--] = 0x2;//T

		if((psnmp->msgGlobalData.seqFlag)&1)
		{
			len = encode_integer(tmp_int , psnmp->msgGlobalData.msgID);
			memcpy(msg + pos -len + 1, tmp_int, len); 
		}
		else 
			len = 0;

		pos -= len; 
		msg[pos--] = len;
		msg[pos--] = 0x2;//T

		//len = stack[--pstack] - pos; 	//pop
		len = outlen2 -pos;
		insert_length(msg, pos, len); 							//L
		msg[pos--] = 	0x30;
	}
	else
	{
		//community

		if(psnmp->pdu_type == PDU_TRAP)
		{
			memcpy(msg + pos - 5, (BYTE *)COMMUNITY, 6); 			//V
			pos -= 6; 
			msg[pos--] = 6; 
		}
		else
		{
#if SNMP_ANY_COMMUNITY
			psnmp->community[15] = 0; 							//max length = 15
			comm_len = strlen(psnmp->community); 

			memcpy(msg + pos - comm_len + 1, (BYTE *)psnmp->community, comm_len); 			//V
			pos -= comm_len; 
			msg[pos--] = comm_len; 
#else						//use "public" as community
			memcpy(msg + pos - 5, (BYTE *)COMMUNITY, 6); 			//V
			pos -= 6; 
			msg[pos--] = 6; 
#endif
		}
		if(pos<4)   return 0;
		/*added by LHB, Oct. 30 04 */
		if(pstack<2) return 0;
		/*added by LHB, Oct. 30 04 */
												//L
		msg[pos--] = 0x04; 								//T
	}
		//version
	//msg[pos--] = SNMP_V2; 								//V
	msg[pos--] = snmpVersion;// psnmp->msgVersion; 								//V
	msg[pos--] = 1; 									//L
	msg[pos--] = 0x02; 								//T
	//head
	len = stack[--pstack] - pos; 	//pop
	if(len<0) return 0;
	/*added by LHB, Oct. 30 04 */
	insert_length(msg, pos, len); 							//L
	msg[pos--] = 0x30; 									//T
	len = stack[--pstack] - pos; 	//pop
	if(len<0) return 0;	
	/*added by LHB, Oct. 30 04 */
	if((psnmp->msgGlobalData.msgFlags&1) && (snmpVersion == SNMP_V3))//auth
	{
		snmpV3AuthenticateOutgoingMsg (v3_engine[index].authKey,				 /*secret key for authentication*/
										  	AUTH_KEY_LEN,
										  	&msg[pos+1],				 /* unauthenticated complete message*/
										  	len,
										  	pAuthPara,		 /* authenticationParamemeter	 */
										  	&outlen
										 );
	}
	if(len >= 1514)//MAX_CONTENT_LEN)
	{
			snmp_debug(SNMPDB_ERR, "Build_msg 's length(%d) exceed limit:varindex = %d", len, var_num); 
			pvar->msglen = 0; 
			error_status = 1; 
			return 0;
	}
	memcpy(pbuf, msg + pos + 1, len); 
	//if(error_status)
	//	return 0; 
	//else
	boots++;

#if SNMP_DEBUG_LOG
	snmpLogInfo("end of build_snmpmsg()");
#endif
		return len; 
}

int parse_snmpmsg(BYTE *msgin, int msglen, snmp_pdu *psnmp, BYTE *error_status)
{
	u_int 		pos = 0, idend; 
	u_int 		pdu_len,offset;
	int		 len, tmplen; 
	BYTE		idlen, varindex = 0; 
	var_list	*pvar; 
	DWORD		*poid; 
	BYTE		*pAuthPtr;
#if SNMP_DEBUG_LOG
	char		debugBuf[512];
	sprintf(debugBuf,"parse_snmpmsg(), msg len = %d",msglen);
	snmpLogInfo(debugBuf);
#endif

	if(msglen > 1536 || msglen < 0)
	{
		return -1; 
	}
	psnmp->error_status = 0;
	if(msgin[pos++] != 0x30)			//T
	{
		snmp_debug(SNMPDB_ERR, "parse_snmpmsg0: Wrong Encoding of SNMP Message. pos = %d", pos - 1); 
		snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
		return -1; 
	}
	
	if((tmplen = get_len(msgin + pos, &len)) < 0)	//L
	{
		snmp_debug(SNMPDB_ERR, "parse_snmpmsg1: Wrong Encoding of Length. pos = %d", pos - 1); 
		snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
		return -1; 
	}

	pos += tmplen; 

	if(pos + len > msglen)	//check length
	{
		snmp_debug(SNMPDB_ERR, "parse_snmpmsg2: Message's length check error"); 
		snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
		return -1; 
	}
	else				//correct length
	{
		msglen = pos + len; 
	}

//version------>
	if(msgin[pos] != 2 || msgin[pos + 1] != 1)
	{
		snmp_debug(SNMPDB_ERR, "parse_snmpmsg3: Wrong Encoding of SNMP Message. pos = %d", pos); 
		snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
		return -1; 
	}
	pos += 2; 

	if(msgin[pos] != SNMP_V1 && msgin[pos] != SNMP_V2 && msgin[pos] != SNMP_V3)
	{
		snmp_debug(SNMPDB_ERR, "parse_snmpmsg4: Version check error, Version = %d", msgin[pos]); 
		snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
		return -1;
	}
	psnmp->msgVersion = msgin[pos];
	pos++; 
	if(psnmp->msgVersion==SNMP_V3)
	{
		if(msgin[pos++]!=0x30)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg5: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		
		if((tmplen = get_len(msgin + pos, &len)) < 0)	//L
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg111: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		else if((pos + len > msglen)||(len > msglen))	//check length
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg69: Message's length check error"); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		pos += tmplen; 

		//tmplen = msgin[pos++]; //pierre
		//parse_hd
		if(msgin[pos++]!=2)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg6: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		tmplen = msgin[pos++]%5;
		psnmp->msgGlobalData.msgID = decode_integer(&msgin[pos], tmplen);
		pos +=tmplen;
		if(msgin[pos++]!=2)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg7: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		tmplen = msgin[pos++]%5;
		psnmp->msgGlobalData.msgMaxSize = decode_integer(&msgin[pos], tmplen);
		pos +=tmplen;
		if(msgin[pos++]!=4)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg8: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		tmplen = msgin[pos++]%5;
		psnmp->msgGlobalData.msgFlags = decode_integer(&msgin[pos], tmplen);
		pos +=tmplen;
		if(msgin[pos++]!=2)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg9: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		tmplen = msgin[pos++]%5;
		psnmp->msgGlobalData.msgSecurityModel = decode_integer(&msgin[pos], tmplen);
		pos +=tmplen;
		psnmp->msgGlobalData.seqFlag = 0xff;
		//parse_securityPara
		psnmp->msgSecurityParameters.seqFlag = 0;

		if(msgin[pos++]!=4)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg10: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		tmplen = msgin[pos++];
		if(msgin[pos++] != 0x30)			//T
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg11: Wrong Encoding of SNMP Message. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		if((tmplen = get_len(msgin + pos, &len)) < 0)	//L
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg12: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		else if((pos + len > msglen)||(len > msglen))	//check length
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg70: Message's length check error"); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		pos +=tmplen;
		if(msgin[pos++]!=4)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg13: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		tmplen = msgin[pos++];
		if(tmplen != 0)
			psnmp->msgSecurityParameters.seqFlag |= 1; 
		memcpy(psnmp->msgSecurityParameters.msgAuthoritativeEngineID,&msgin[pos], tmplen);
		pos +=tmplen;
		if(msgin[pos++]!=2)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg14: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		tmplen = msgin[pos++];
		if(tmplen != 0)
			psnmp->msgSecurityParameters.seqFlag |= 2;
		psnmp->msgSecurityParameters.msgAuthoritativeEngineBoots = decode_integer(&msgin[pos], tmplen);
		pos +=tmplen;
		if(msgin[pos++]!=2)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg15: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		tmplen = msgin[pos++];
		if(tmplen != 0)
			psnmp->msgSecurityParameters.seqFlag |= 4;
		psnmp->msgSecurityParameters.msgAuthoritativeEngineTime = decode_integer(&msgin[pos], tmplen);
		pos +=tmplen;
		if(msgin[pos++]!=4)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg16: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		tmplen = msgin[pos++];
		if(tmplen != 0)
			psnmp->msgSecurityParameters.seqFlag |= 8;
		memcpy(psnmp->msgSecurityParameters.msgUserName,&msgin[pos], tmplen);
		psnmp->msgSecurityParameters.msgUserName[tmplen]=0;
		pos +=tmplen;	
		if(msgin[pos++]!=4)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg17: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		tmplen = msgin[pos++];
		if(tmplen != 0)
			psnmp->msgSecurityParameters.seqFlag |= 16;
		memcpy(psnmp->msgSecurityParameters.msgAuthenticationParameters,&msgin[pos], tmplen);
		pAuthPtr = msgin+pos;
		pos +=tmplen;	
		if(msgin[pos++]!=4)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg18: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		tmplen = msgin[pos++];
		if(tmplen != 0)
			psnmp->msgSecurityParameters.seqFlag |= 32;
		memcpy(psnmp->msgSecurityParameters.msgPrivacyParameters,&msgin[pos], tmplen);
		pos +=tmplen;

		if((psnmp->msgGlobalData.msgFlags&0x03)==3)//auth & privacy //pierre 
		{
			if(msgin[pos++]!=4)
			{
				snmp_debug(SNMPDB_ERR, "parse_snmpmsg19: Wrong Encoding of Length. pos = %d", pos - 1); 
				snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
				return -1; 
			}
			if((tmplen = get_len(msgin + pos, &len)) < 0)	//L
			{
				snmp_debug(SNMPDB_ERR, "parse_snmpmsg20: Wrong Encoding of Length. pos = %d", pos - 1); 
				snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
				return -1; 
			}
			else if((pos + len > msglen)||(len > msglen))	//check length
			{
				snmp_debug(SNMPDB_ERR, "parse_snmpmsg71: Message's length check error"); 
				snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
				return -1; 
			}
			pos +=tmplen;

		}
		else	
		{
			if(msgin[pos++] != 0x30)			//T
			{
				snmp_debug(SNMPDB_ERR, "parse_snmpmsg21: Wrong Encoding of SNMP Message. pos = %d", pos - 1); 
				snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
				return -1; 
			}
			if((tmplen = get_len(msgin + pos, &len)) < 0)	//L
			{
				snmp_debug(SNMPDB_ERR, "parse_snmpmsg22: Wrong Encoding of Length. pos = %d", pos - 1); 
				snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
				return -1; 
			}
			else if((pos + len > msglen)||(len > msglen))	//check length
			{
				snmp_debug(SNMPDB_ERR, "parse_snmpmsg72: Message's length check error"); 
				snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
				return -1; 
			}
			pos +=tmplen;

		}
			
		if(psnmp->msgGlobalData.msgFlags&0x1)//auth
		{
			int ret, index;			
			index = find_engine(psnmp->msgSecurityParameters.msgUserName);
			if(index < 0)
			{
				snmp_debug(SNMPDB_ERR, "parse_snmpmsg: unknow userName = %s", psnmp->msgSecurityParameters.msgUserName); 
				*error_status = UnknownUserNames;
			}
			else
			{
				ret = snmpV3AuthenticateIncomingMsg(v3_engine[index].authKey, 
							AUTH_KEY_LEN, 
							//msgin+pos, 
							//len, 
							msgin, 
							len+pos, 
							//psnmp->msgSecurityParameters.msgAuthenticationParameters, MD5_DIGEST_90_LEN);
							pAuthPtr, MD5_DIGEST_90_LEN);
				if(ret<0)
				{
					snmp_debug(SNMPDB_ERR, "parse_snmpmsg: Auth failed of userName = %s", psnmp->msgSecurityParameters.msgUserName); 
					snmp_showbuf(SNMPDB_ERR, msgin, msglen);
					*error_status = WrongDigests;
					//return -1; 
				}	
				if(psnmp->msgGlobalData.msgFlags&0x2)//privacy
				{
					memcpy(psnmp->msgData.encryptedPDU, &msgin[pos], len);
					if(snmpV3DecryptData(v3_engine[index].privacyKey, AUTH_KEY_LEN, (u8 *)psnmp->msgSecurityParameters.msgPrivacyParameters,
						8, (u8 *)psnmp->msgData.encryptedPDU, len,
						msgin+pos, (u16 *)&tmplen)<0)
					{
						snmp_debug(SNMPDB_ERR, "parse_snmpmsg: Decrypt failed of userName = %s", psnmp->msgSecurityParameters.msgUserName); 
						snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
						*error_status = DecryptionErrors;
						return 1; 
					}	
				}
			}
		}

		if(msgin[pos]== 0x30)
		{
			pos++;
			//tmplen = get_len(msgin + pos, &len);
			if((tmplen = get_len(msgin + pos, &len)) < 0)	//L
			{
				snmp_debug(SNMPDB_ERR, "parse_snmpmsg73: Wrong Encoding of Length. pos = %d", pos - 1); 
				snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
				return -1; 
			}
			else if((pos + len > msglen)||(len > msglen))	//check length
			{
				snmp_debug(SNMPDB_ERR, "parse_snmpmsg74: Message's length check error"); 
				snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
				return -1; 
			}
			pos +=tmplen;
		}
		
		if(msgin[pos++]!= 4)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg23: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}		
		//tmplen = get_len(msgin + pos, &len);
		if((tmplen = get_len(msgin + pos, &len)) < 0)	//L
			{
				snmp_debug(SNMPDB_ERR, "parse_snmpmsg75: Wrong Encoding of Length. pos = %d", pos - 1); 
				snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
				return -1; 
			}
		else if((pos + len > msglen)||(len > msglen))	//check length
			{
				snmp_debug(SNMPDB_ERR, "parse_snmpmsg76: Message's length check error"); 
				snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
				return -1; 
			}
		pos +=tmplen;
		
		psnmp->msgData.plaintext.seqFlag = 0;
		if(len>0)
			psnmp->msgData.plaintext.seqFlag |=1;
		memcpy(psnmp->msgData.plaintext.contextEngineID, &msgin[pos], len);
		pos +=len;

		if(msgin[pos++]!= 4)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg24: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		tmplen = msgin[pos++];
		if(tmplen>0)
			psnmp->msgData.plaintext.seqFlag |=2;			
		memcpy(psnmp->msgData.plaintext.contextName, &msgin[pos], tmplen);
		psnmp->msgData.plaintext.contextName[tmplen]=0;
		pos +=tmplen;
		
	}
	else
	{
//community------>
		
		if(msgin[pos++] != 4)						//T
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg25: Wrong Encoding of SNMP Message. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 	
		}
		if((tmplen = get_len(msgin + pos, &len)) < 0)			//L
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg26: Wrong Encoding of Length. pos = %d", pos); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		pos += tmplen; 

		if(len > 32)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg27: Invalid Length of community. pos = %d, len = %d", pos - tmplen, len); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}

		if((msgin[pos + len] & 0x1F) != PDU_TRAP)
		{
#if SNMP_ANY_COMMUNITY
			if(memcmp(msgin + pos, psnmp->community, len) != 0)	//V
			{
				//authorization error
				psnmp->error_status = 16; 
				snmp_debug(SNMPDB_ERR, "parse_snmpmsg28: Authorization error. COMMUNITY(%s):", psnmp->community); 
				snmp_showbuf(SNMPDB_ERR, msgin + pos, len); 
			}
#else		//"public" as community
			if(memcmp(msgin + pos, COMMUNITY, len) != 0)	//V
			{
				//authorization error
				psnmp->error_status = 16; 
				snmp_debug(SNMPDB_ERR, "parse_snmpmsg29: Authorization error. COMMUNITY(%s):", COMMUNITY); 
				snmp_showbuf(SNMPDB_ERR, msgin + pos, len); 
			}
#endif
		}
		pos += len; 
	}
//PDU------>
	psnmp->pdu_type = msgin[pos++] & 0x1F; 	//T

	if(psnmp->pdu_type == PDU_REPORT)
	{
		printf("snmp receive REPORT\n");
		printf("\n");
	}
	if((tmplen = get_len(msgin + pos, &len)) < 0)			//L
	{
		snmp_debug(SNMPDB_ERR, "parse_snmpmsg30: Wrong Encoding of Length. pos = %d", pos - 1); 
		snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
		return -1; 
	}
	else if((pos + len > msglen)||(len > msglen))	//check length
			{
				snmp_debug(SNMPDB_ERR, "parse_snmpmsg77: Message's length check error"); 
				snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
				return -1; 
			}
	pos += tmplen; 
	pdu_len = len;
	offset = pos; //pierre
/*
	if(pos + len != msglen)	//check length
	{
		snmp_debug(SNMPDB_ERR, "parse_snmpmsg: Length check error"); 
		snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
		return -1; 
	}
*/
	//request-id------>
	if(msgin[pos++] != 2)									//T
	{
		//wrong encoding
		if(psnmp->error_status == 0)
			psnmp->error_status = 9; 
		snmp_debug(SNMPDB_ERR, "parse_snmpmsg50: Wrong encoding of SNMP message. pos = %d", pos); 
		snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
	}

	if((tmplen = get_len(msgin + pos, &len)) < 0)						//L
	{
		snmp_debug(SNMPDB_ERR, "parse_snmpmsg51: Wrong Encoding of Length. pos = %d", pos - 1); 
		snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
		return -1; 
	}
	pos += tmplen; 
	if(len > 5)
	{
		snmp_debug(SNMPDB_ERR, "parse_snmpmsg52: ASN.1 encoding error.pos = %d", pos - 4); 
		snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
		return -1; 
	}
	psnmp->request_id = decode_integer(msgin + pos, len); 	//V
	pos += len; 
	//error status------>
	//add by yizane start
	if(psnmp->pdu_type==PDU_GETBULK)
	{
		if(msgin[pos++] != 2)		//T
		{
			//wrong encoding
			if(psnmp->error_status == 0)
				psnmp->error_status = 9; 
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg53: Wrong encoding of SNMP message. pos = %d", pos); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen);			
		}			
		if((tmplen = get_len(msgin + pos, &len)) < 0)						//L
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg54: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}				
		pos += tmplen; 
		if(len > 5)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg55: ASN.1 encoding error.pos = %d", pos - 4); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}		
		idend = pos + len; 		
		psnmp->non_repeaters = 0;
		do														//V
		{
			if((msgin[pos] & 0x80) == 0)
				psnmp->non_repeaters |= msgin[pos]; 
			else
				psnmp->non_repeaters = (psnmp->non_repeaters | (msgin[pos] & 0x7F)) << 7; 
			pos++; 
		}while(pos < idend); 			
	}	
	else	
	{
		if(msgin[pos] != 2 || msgin[pos + 1] != 1)				//T L
		{
			//wrong encoding
			if(psnmp->error_status == 0)
				psnmp->error_status = 9; 
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg56: Wrong encoding of SNMP message. pos = %d", pos); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
		}
		pos += 2; 
	
		if(psnmp->error_status == 0){
			psnmp->error_status = msgin[pos++]; 				//V
		}else
			pos++; 
	}	
		
	//error index------>
	if(psnmp->pdu_type==PDU_GETBULK)
	{		
		if(msgin[pos++] != 2)		//T
		{
			//wrong encoding
			if(psnmp->error_status == 0)
				psnmp->error_status = 9; 
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg57: Wrong encoding of SNMP message. pos = %d", pos); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen);			
		}			
		if((tmplen = get_len(msgin + pos, &len)) < 0)						//L
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg58: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}				
		pos += tmplen; 
		if(len > 5)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg59: ASN.1 encoding error.pos = %d", pos - 4); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}		
		idend = pos + len; 		
		psnmp->max_repetitions =0;
		do														//V
		{
			if((msgin[pos] & 0x80) == 0)
				psnmp->max_repetitions |= msgin[pos]; 
			else
				psnmp->max_repetitions = (psnmp->max_repetitions | (msgin[pos] & 0x7F)) << 7; 
			pos++; 
		}while(pos < idend); 			
	}
	else	
	{
		if(msgin[pos] != 2 || msgin[pos + 1] != 1)				//T L
		{
			//wrong encoding
			if(psnmp->error_status == 0)
				psnmp->error_status = 9; 
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg60: Wrong Encoding of SNMP message. pos = %d", pos); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
		}
		pos += 2; 
		psnmp->error_index = msgin[pos++]; 					//V
	}
	//add by yizane end
	
	//variable-binding list------>
	if(msgin[pos++] != 0x30)								//T
	{
		//wrong encoding
		if(psnmp->error_status == 0)
			psnmp->error_status = 9; 
		snmp_debug(SNMPDB_ERR, "parse_snmpmsg61: Wrong encoding of SNMP message. pos = %d", pos); 
		snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
	}

	if((tmplen = get_len(msgin + pos, &len)) < 0)						//L
	{
		snmp_debug(SNMPDB_ERR, "parse_snmpmsg62: Wrong Encoding of Length. pos = %d", pos - 1); 
		snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
		return -1; 
	}
	pos += tmplen; 
/*
	if(pos + len != msglen)	//check length
	{
		snmp_debug(SNMPDB_ERR, "parse_snmpmsg: Message's Length check error"); 
		snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
		return -1; 
	}
*/
	if(pos >= msglen)
	{
		psnmp->var_num = 0;
		return 1;// no varibale
	}
	//variable------>
	varindex = 0; 
	do
	{
		pvar = &psnmp->var[varindex]; 
		
		poid = pvar->oid; 
		if(msgin[pos++] != 0x30)								//T
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg63: Wrong encoding of SNMP message. pos = %d", pos); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}

		if((tmplen = get_len(msgin + pos, &len)) < 0)						//L
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg64: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		pos += tmplen; 
		//OID------>
		if((msgin[pos++] & 0x3F) != 0x06)							//T
		{
			if(psnmp->error_status == 0)
			{
				psnmp->error_status = 9; 
			}
		}

		if((tmplen = get_len(msgin + pos, &len)) < 0)						//L
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg65: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		pos += tmplen; 

		if(len > OID_MAXLEN)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg66: OID length exceed limit. oidlen = %d", len); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		
		memset(poid, 0, sizeof(DWORD) * OID_MAXLEN); 
		idend = pos + len; 		
		poid[0] = msgin[pos] / 40; 
		poid[1] = msgin[pos++] % 40; 
		idlen = 2; 
		do														//V
		{
			if((msgin[pos] & 0x80) == 0)
				poid[idlen++] |= msgin[pos]; 
			else
				poid[idlen] = (poid[idlen] | (msgin[pos] & 0x7F)) << 7; 
			pos++; 
		}while(pos < idend && idlen < OID_MAXLEN); 

		pvar->oidlen = idlen; 
		//value
		pvar->vartype = msgin[pos++]; 									//T

		if((tmplen = get_len(msgin + pos, &len)) < 0)						//L
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg67: Wrong Encoding of Length. pos = %d", pos - 1); 
			snmp_showbuf(SNMPDB_ERR, msgin, msglen); 
			return -1; 
		}
		pos += tmplen; 

		if(len > 1500 || len > msglen-pos)
		{
			snmp_debug(SNMPDB_ERR, "parse_snmpmsg68: Error length of variant.varindex = %d, length = %d", varindex, len); 
			return -1; 
		}
		else if(len > 0)
		{
			memcpy(pvar->msg, msgin + pos, len); 						//V
		}
		pos += len; 
		pvar->msglen = len; 
		varindex++;
	//}while(pos < msglen); 
	}while((pos-offset) < pdu_len); 

	psnmp->var_num = varindex; 

#if SNMP_DEBUG_LOG
	snmpLogInfo("end of parse_snmpmsg()");
#endif
	return 1; 
}

/********************************************************************/
DWORD assign_rid()
{
	static DWORD	rid = 1; 

	rid = (rid-1)%0x10000000+2; 
	return rid; 
}

BYTE *getmem(int nsize)
{
	//static BYTE	watchPoint;
	static BYTE		heap[HEAP_SIZE]; 			//500K
	static int		heap_pos = 0;
	//static BYTE	watchPoint2;
	if(heap_pos+nsize>HEAP_SIZE)
		return NULL; 
	else
	{
		memset(heap+heap_pos, 0, nsize); 
		heap_pos+= nsize; 
		//printf("assigned memory = %d Byte\n", heap_pos); 
		return &heap[heap_pos-nsize]; 
	}
}
/********************************************************************/

int get_len(BYTE *asnbuf, int *len)
{
	u_int		pos = 0, lenbyte; 

	if((asnbuf[pos] & 0x80) == 0)
		*len = asnbuf[pos++] & 0x7F; 
	else
	{
		*len = 0; 
		lenbyte = asnbuf[pos++] & 0x7F; 
		if(lenbyte > 4 || lenbyte < 0)
			return -1; 

		if(lenbyte == 0)
		{
			*len = -1; 
			return 1; 
		}
		else
		{
			while(lenbyte-- > 0)
				*len = (*len) * 0x100 + asnbuf[pos++]; 
		}
	}
	return pos; 
} 

BYTE encode_integer(BYTE *buf, DWORD val)
{
	if(val < 128)
	{
		buf[0] = val; 
		return 1; 
	}
	else if(val < 0x8000)
	{
		buf[0] = val >> 8; 
		buf[1] = val; 
		return 2; 
	}
	else if(val < 0x800000)
	{
		buf[0] = val >> 16; 
		buf[1] = val >> 8; 
		buf[2] = val; 
		return 3; 
	}
	else if(val < 0x80000000)
	{
		buf[0] = val >> 24; 
		buf[1] = val >> 16; 
		buf[2] = val >> 8; 
		buf[3] = val; 
		return 4; 
	}
	else
	{
		buf[0] = 0; 
		buf[1] = val >> 24; 
		buf[2] = val >> 16; 
		buf[3] = val >> 8; 
		buf[4] = val; 
		return 5; 
	}
}

DWORD decode_integer(BYTE *buf, BYTE len)
{
	BYTE	i = 0; 
	DWORD	val = 0; 
	while(i < len)
		val = (val << 8) | buf[i++]; 
	return val; 
}

int add_security_engine(snmpV3SecurityPara *engine)
{
	return 1;
}

int delete_security_engine(snmpV3SecurityPara *engine)
{
	return 1;
}

int check_security_engine(snmpV3SecurityPara *engine)
{
	return 1;
}

int load_engine_para(snmp_pdu *engine, DWORD ip, WORD port)
{
	int i=0, first_level=-1, sec_level=-1, third_level=-1,server_index;
	static int msgID=0;
	snmpV3SecurityPara *ptr=NULL;
	
	for(i=0; i<MAX_ENGINE; i++)
	{
		if(v3_engine[i].engineType==1)
		{
			if(ip == v3_engine[i].remote_ip)
			{
				if(port==v3_engine[i].remote_port && v3_engine[i].remote_port!=0)
				{
					first_level = i;
					break;
				}else if(v3_engine[i].remote_port==0)
				{
					sec_level = i;
				}
				
			}
		}else if(v3_engine[i].engineType==2)
		{
			third_level= i;
		}
	}

	if(first_level<0 && sec_level<0 && third_level<0)
		return -1;
	if(third_level>=0)
	{
			server_index = third_level;
	}
	if(sec_level>=0)
	{
			server_index = sec_level;
	}
	if(first_level>=0)
	{
			server_index = first_level;
	}
		
	ptr = &v3_engine[server_index];
	engine->msgGlobalData.seqFlag = 0xF;
	engine->msgGlobalData.msgID=msgID++ ;
	engine->msgGlobalData.msgMaxSize = SNMP_VAR_MAX;
	engine->msgGlobalData.msgSecurityModel = 3;
	engine->msgGlobalData.msgFlags = ptr->securityLevel;
	engine->msgVersion = SNMP_V3;
	engine->msgData.plaintext.seqFlag = 0xf;
	memcpy(engine->msgData.plaintext.contextEngineID, ptr->contextEngineID,32);
	memcpy(engine->msgData.plaintext.contextName, ptr->contextName,32);
	engine->msgSecurityParameters.seqFlag = 0xff;
	memcpy(engine->msgSecurityParameters.msgAuthoritativeEngineID, ptr->securityEngineID,32);
//	memcpy(engine.msgSecurityParameters.msgAuthenticationParameters, ptr->authPassword,32);
	memcpy(engine->msgSecurityParameters.msgUserName, ptr->securityUserName, 32);
	engine->msgSecurityParameters.msgAuthoritativeEngineBoots = ptr->boots;
	engine->msgSecurityParameters.msgAuthoritativeEngineTime = ptr->authInTime;
//	memcpy(engine.msgSecurityParameters.msgPrivacyParameters, ptr->privacyProtocol, 32);
	return 0;
}

void init_engine_para()
{
	int i;
	snmpV3SecurityPara *psnmp;

	for(i=0;i < MAX_ENGINE; i++)
	{
		psnmp = &v3_engine[i];
		if(strlen(psnmp->securityUserName)==0)
			continue;
		if(psnmp->engineType==0)
			memcpy(securityEngineID,  psnmp->securityEngineID, 32);
		password_to_key_md5((u8 *)psnmp->privacyPassword, strlen(psnmp->privacyPassword), (u8 *)psnmp->securityEngineID, 12, psnmp->privacyKey);
        	password_to_key_md5((u8 *)psnmp->authPassword, strlen(psnmp->authPassword), (u8 *)psnmp->securityEngineID, 12, psnmp->authKey);       	
	}
	
}

int init_engine(char *engine_name)
{
	int i;
	snmpV3SecurityPara *psnmp;

	for(i=0;i < MAX_ENGINE; i++)
	{
		psnmp = &v3_engine[i];
		if(strlen(psnmp->securityUserName)==0 )
			continue;
		if(strcmp(psnmp->securityUserName, engine_name)!=0 )
			continue;
		password_to_key_md5((u8 *)psnmp->privacyPassword, strlen(psnmp->privacyPassword), (u8 *)psnmp->securityEngineID, 12, psnmp->privacyKey);
        	password_to_key_md5((u8 *)psnmp->authPassword, strlen(psnmp->authPassword), (u8 *)psnmp->securityEngineID, 12, psnmp->authKey);       	
	}
	return 1;
}

int load_snmp_para()
{
	return 1;
}
void update_engine_authtime()
{
	int i,len;
	
	for(i=0; i<MAX_ENGINE; i++)
	{
		len = strlen(v3_engine[i].securityUserName);
		if(len <=0) continue;
		v3_engine[i].authInTime++;
	}
	manager_engine.authInTime ++;
}

int find_engine(char *userName)
{
	int i,len;
	int len1;
	
	len1 = strlen(userName);
	
	for(i=0; i<MAX_ENGINE; i++)
	{
		len = strlen(v3_engine[i].securityUserName);
		if(len <=0 || len!=len1) continue;
		if(!strncmp(v3_engine[i].securityUserName, userName, len))
			return i;
	}
	return -1;
}

int find_engine_server(char *userName, DWORD ip)
{
	int i,len;
	int len1;
	
	len1 = strlen(userName);
	
	for(i=0; i<MAX_ENGINE; i++)
	{
		len = strlen(v3_engine[i].securityUserName);
		if(len <=0 ||len!=len1) continue;
		if((!strncmp(v3_engine[i].securityUserName, userName, len))&&(v3_engine[i].engineType==1))
			return i;
	}
	return -1;
	
}


int ReadManagerPara(char *s )
{
	if(strstr(s, "engineID=")!=NULL)
	{
		FILE *fp=NULL;
		fp = fopen("./conf/manager_engine.conf","r");
		if(fp != NULL)
		{
			fread(&manager_engine,sizeof(snmpV3SecurityPara),1,fp);
			fclose(fp);
		}
		AsciiToBcd((BYTE *)manager_engine.securityEngineID, s+9, 24);
		manager_engine.authInTime = 0;
		manager_engine.boots ++;
		fp = fopen("./conf/manager_engine.conf","w");
		if(fp != NULL)
		{
			fwrite(&manager_engine,sizeof(snmpV3SecurityPara),1,fp);
			fclose(fp);
		}
		
		return 1;
	}
	return 0;
}

int ReadEngineUserPara(char *s, int index)
{
	if(index>=MAX_ENGINE)
		return 0;

	s[strlen(s)-1]=0;
	if(strstr(s, "userName=")!=NULL)
	{
		s[strlen(s)]=0;
		strncpy(v3_engine[index].securityUserName, s+9, 32);		
		return 0;
	}
	else if(strstr(s, "authPassword=")!=NULL)
	{
		strncpy(v3_engine[index].authPassword, s+13, 32);
		
		return 0;
	}
	else if(strstr(s, "privacyPassword=")!=NULL)
	{
		strncpy(v3_engine[index].privacyPassword, s+16, 32);
		
		return 0;
	}	
	else if(strstr(s, "engineID=")!=NULL)
	{
		//strncpy(v3_engine[index].securityEngineID, s+9, 32);
		AsciiToBcd((BYTE *)v3_engine[index].securityEngineID, s+9, 24);
		return 0;
	}
	else if(strstr(s, "engineType=")!=NULL)
	{
		v3_engine[index].engineType = atoi(s+11);
		
		return 0;
	}else if(strstr(s, "securityLevel=")!=NULL)
	{
		v3_engine[index].securityLevel= atoi(s+14);		
		return 0;
	}else if(strstr(s, "boots=")!=NULL)
	{
		v3_engine[index].boots= atoi(s+6);		
		return 0;
	}else if(strstr(s, "authInTime=")!=NULL)
	{
		v3_engine[index].authInTime= atoi(s+11);		
		return 0;
	}else if(strstr(s, "contextName=")!=NULL)
	{
		if(s[12] != 0x3d ) //\d
		strncpy(v3_engine[index].contextName, s+12, 32);
		else
		memset(v3_engine[index].contextName,0,32);
		return 0;
	}else if(strstr(s, "contextEngineID=")!=NULL)
	{
		//strncpy(v3_engine[index].contextEngineID, s+16, 32);
		AsciiToBcd((BYTE *)v3_engine[index].contextEngineID, s+16, 24);
		return 0;
	}else if(strstr(s, "remoteIp=")!=NULL)
	{
		//strncpy(v3_engine[index].contextEngineID, s+16, 32);
		v3_engine[index].remote_ip=inet_addr(s+9);		
		return 0;
	}else if(strstr(s, "remotePort=")!=NULL)
	{
		v3_engine[index].remote_port=atoi(s+11);		
		return 0;
	}else if(strstr(s, "admin_state=")!=NULL)
	{
		//strncpy(v3_engine[index].contextEngineID, s+16, 32);
		v3_engine[index].admin_state=atoi(s+12);		
		return 0;
	}
	return 0;
}

void snmp_readpara()
{
	char	s[1024]={0};
	int		len, index;
	
	BYTE	state = 0;
	FILE	*fp;
	
	fp = fopen(snmpconfile,"rb");

	if (fp==NULL)
	{
		printf("snmpconfig file %s missed!!\n",snmpconfile);
		return;
	}

    s[0] = 0;
	while ( fgets(s,1024,fp) != (char *)0 )
	{
		if ( (int *)strchr(s,'#') != NULL ) continue;
		if ( (len=strlen(s))==0 ) continue;

		if ( strstr(s,"[engine-") != NULL )
		{
			index = atoi(s+8);
			state = 1;
			continue;
		}
		else if(strstr(s,"[manager]") != NULL)
		{
			state = 3;
			continue;
		}
		else if ( strstr(s,"[version-") != NULL )
		{
			snmpVersion = atoi(s+9);
			state = 2;
			continue;
		}
		switch (state)
		{
		case 1:
			if (ReadEngineUserPara(s, index))
				state = 0;
			break;
		case 3:
			ReadManagerPara(s);
			break;
		default:
			break;
		}
	}
	fclose(fp);
}


int snmp_write_parameter()
{
	int	i;
	FILE *snmpfp;
	struct in_addr ad1;
	char str[256]={0};
	
	snmpfp = fopen(snmpconfile,"w");
	if (snmpfp == NULL)
		return -1;

	fprintf(snmpfp,"[version-%d]\n", snmpVersion);
	fprintf(snmpfp,"\n");
	fprintf(snmpfp,"[manager]\n");
	BcdToAscii(str, (BYTE *)manager_engine.securityEngineID, 24);
	fprintf(snmpfp,"engineID=%s\n",str);
	fprintf(snmpfp,"\n");
	for(i=0;i<MAX_ENGINE; i++)
	{
		if(strlen(v3_engine[i].securityUserName)==0)
			continue;
		
		fprintf(snmpfp,"[engine-%d]\n", i);
		fprintf(snmpfp,"userName=%s\n", v3_engine[i].securityUserName);
		fprintf(snmpfp,"admin_state=%d\n", v3_engine[i].admin_state);
		fprintf(snmpfp,"securityLevel=%d\n", v3_engine[i].securityLevel);
		fprintf(snmpfp,"engineType=%d\n", v3_engine[i].engineType);		
		fprintf(snmpfp,"authPassword=%s\n", v3_engine[i].authPassword);
		fprintf(snmpfp,"privacyPassword=%s\n", v3_engine[i].privacyPassword);
		memcpy(&ad1, &v3_engine[i].remote_ip, 4);
		fprintf(snmpfp,"remoteIp=%s\n", inet_ntoa(ad1));
		fprintf(snmpfp,"remoteIp=%d\n", v3_engine[i].remote_port);
		BcdToAscii(str, (BYTE *)v3_engine[i].securityEngineID, 24);
		fprintf(snmpfp,"engineID=%s\n",str);	
		fprintf(snmpfp,"contextName=%s\n", v3_engine[i].contextName);
		BcdToAscii(str, (BYTE *)v3_engine[i].contextEngineID, 24);
		fprintf(snmpfp,"contextEngineID=%s\n",str);		
		fprintf(snmpfp,"\n");
	}
	fprintf(snmpfp,"\n");
	fclose(snmpfp);
	return 1;
}
