/**************************************************/
/*Title:    snmpdebug.c                           */
/*Descr:    Debug Module of SNMP Agent            */
/*Author:   Liang Hanxi                           */
/*Create:   2002-4-1                              */
/*Modify:                                         */
/**************************************************/
#include	"./include/heartbeat.h"
static unsigned long	l_starttime;
extern snmp_csta		SnmpCsta[96];
extern int				snmp_ins;
extern heartbeat_shm	*HbShm;

int snmp_setmib(BYTE oidlen, DWORD *oid, BYTE *pdata,WORD datalen);
int snmp_getmib(BYTE oidlen, DWORD *oid, BYTE *pdata,BYTE *vartype);
int snmp_getsys(BYTE oidlen, DWORD *oid, BYTE *pdata,BYTE *vartype);
void time_sync(BYTE oidlen,DWORD *oid,BYTE *pdata,WORD len,snmp_addr *addr);
static void submit_snmpcsta(BYTE *pdword,BYTE *pbyte,int len);
/* by simon at 23/9/25 */
extern char SnmpVer[16];

void snmpmib_init()
{
	DWORD		oid[OID_MAXLEN]=SNMP_OID;
	DWORD		sysoid[8]={1,3,6,1,2,1,1};
	l_starttime=time(NULL);
	inquire_getmsg(SNMP_OIDLEN,oid,snmp_getmib);
	inquire_setmsg(SNMP_OIDLEN,oid,snmp_setmib);
	inquire_getmsg(7,sysoid,snmp_getsys);
	inquire_trapmsg(time_sync);
}

int snmp_setmib(BYTE oidlen, DWORD *oid, BYTE *pdata,WORD datalen)
{
	return -1;
	switch(oid[SNMP_OIDLEN])
	{
	case 1:				//Measure
		return -1;		//read only
	case 2:				//Configuration
		switch(oid[SNMP_OIDLEN+1])
		{
		case 1:				//SNMP Parameter
			switch(oid[SNMP_OIDLEN+2])
			{
			case 1:				//Port
				return -1;		//not allow
			case 2:				//password
				return -1;		//not provide now
			}
			break;
		case 2:
			break;
			
		case 3:
			break;
		}
		break;
	case 3:
		break;
	}
}


int snmp_getmib(BYTE oidlen, DWORD *oid, BYTE *pdata,BYTE *vartype)
{
	int			instance;
	snmp_csta	*pcsta;
	switch(oid[SNMP_OIDLEN])
	{
	case 1:				//csta
		if(oidlen!=SNMP_OIDLEN+2)
			return -1;
		instance=oid[SNMP_OIDLEN+1];
		if(instance==snmp_ins || instance>95)
		{
			*vartype=NosuchInstance;
			snmp_debug(SNMPDB_MIB,"csta message not ready.instance=%d",instance);
			return -1;
		}
		pcsta=&SnmpCsta[instance];
		if(pcsta->timestamp ==0)
		{
			snmp_debug(SNMPDB_MIB,"csta message is expired");
			*vartype=5;
			return 0;
		}
		*vartype=4;
		snmp_debug(SNMPDB_MIB, "Respond csta message");
		submit_snmpcsta((BYTE *)&pcsta->timestamp,pdata,sizeof(snmp_csta));
		//memcpy(pdata,(BYTE *)&pcsta->timestamp,sizeof(snmp_csta));
		return sizeof(snmp_csta);
	default:
		return -1;
	}
	return -1;
}


int snmp_getsys(BYTE oidlen, DWORD *oid, BYTE *pdata,BYTE *vartype)
{
	unsigned long	l_time;
	char			contact[50]="InterWAVE";
	char			sysname[50];
	
	switch(oid[oidlen - 1])
	{
	case 1:
		*vartype = 4;
		memcpy(pdata, SnmpVer, strlen(SnmpVer));
		return strlen(SnmpVer);
	case 3:
		l_time=time(NULL);
		*vartype=0x43;
		return encode_integer(pdata,(l_time-l_starttime)*100);
	case 4:
		*vartype=4;
		memcpy(pdata,contact,strlen(contact));
		return strlen(contact);
	case 5:
		*vartype=4;
		sprintf(sysname,"SNMP Agent %d.%d",HbShm->sys_id,HbShm->subsys_id);
		memcpy(pdata,sysname,strlen(sysname));
		return strlen(sysname);
	}
	return -1;
}

#define SNMP_OMC_HB_OID     {1,3,6,1,4,1,1373,2,4,1}
#define SNMP_OMC_HB_OIDLEN  10
#define SNMP_SERNUM_LEN		4

unsigned long long Bcd2Ull(BYTE *pBcd, int BcdLen);

extern unsigned long long	SNMPSerialNumber;
extern BYTE	snmp_synctime_flag;
void time_sync(BYTE oidlen,DWORD *oid,BYTE *pdata,WORD len,snmp_addr *addr)
{
	//DWORD				ObjID[20]=FLATFORM_HB_OID;
	DWORD				OMCHBObjID[20] = SNMP_OMC_HB_OID;
	heartbeat_msg		*pmsg=(heartbeat_msg *)pdata;
	struct timeval		tv;
	struct timezone		tz;
	int				l_time,l_temp;
	static int			master_host=0,master_timeout;

	char oidstring[256];
	char tmpstr[64];
	oidstring[0]=0;
	int i;
	
	if (!snmp_synctime_flag)
		return;

	if(memcmp(&oid[7], &OMCHBObjID[7], (SNMP_OMC_HB_OIDLEN - 7) * 4) == 0)//omc heartbeat
	{//automatic add omc ip into ip list,
	 //if receive omc heartbeat and the omc serial number is equial to the local serial number,
	 //then the platform will send heartbeat if received omc heartbeat
		if ((SNMPSerialNumber==0)	||//support old version, do not have serial number
			(Bcd2Ull(&pdata[39],SNMP_SERNUM_LEN)==SNMPSerialNumber)	)
		{}
		else
			return;
		
	}
	else// if it is not omc heartbeat then return
		return;

	if(pmsg->subsys_id ==HbShm->subsys_id && pmsg->sys_id ==HbShm->sys_id)
		return;

/*
	if(memcmp(&oid[9],&ObjID[9],(FLATFORM_HB_OIDLEN-9)*4)!=0)
	{
		return;
	}
*/	
/*
	if(pmsg->sys_id!=MasterSysID || pmsg->subsys_id!=MasterSubSysID)
		return;
*/	

	if(SNMPSerialNumber!=0){//New version
		if(pdata[26]!=5&&pdata[26]!=7)//not the master omc
			return;	
	}else{//Old version
		if(pdata[21]!=5&&pdata[21]!=7)//not the master omc
			return;
	}
	
	memcpy((BYTE *)&l_temp,pmsg->timestamp,4);
	l_time=htonl(l_temp);						//timestamp in heartbeat
	gettimeofday(&tv,&tz);						//local time

	if(master_host==0 || master_timeout<=0)
	{
		snmp_debug(SNMPDB_SYS, "change master host to %lX",htonl(addr->remote_ip));
		master_host=addr->remote_ip;
		master_timeout=8;
	}

	if(addr->remote_ip != master_host)
	{
		master_timeout--;
		snmp_debug(SNMPDB_SYS, "Found another master,ip=%lX.current master=%lX,timeout=%ld\n",htonl(addr->remote_ip),htonl(master_host),master_timeout);
		return;
	}
	else
		master_timeout=8;

	if(abs(l_time-tv.tv_sec)<2)					//compare
	{
		return;
	}
	timeSync_log("system's time's second is :%ld",tv.tv_sec);
	tv.tv_sec =l_time;
	settimeofday(&tv,&tz);
	for(i=0;i<oidlen;i++)
	{
		sprintf(tmpstr,"%ld.",oid[i]);
		strcat(oidstring,tmpstr);
	}
	timeSync_log("oid is:%s",oidstring);
	timeSync_log("system's time's second is changed to %ld by %lX\n",tv.tv_sec,htonl(addr->remote_ip));

	snmp_debug(SNMPDB_SYS, "system's time is changed by %lX\n",htonl(addr->remote_ip));
}

void submit_snmpcsta(BYTE *pdword,BYTE *pbyte,int len)
{
	int i;
	DWORD		*p1,*p2;
	for(i=0;i<len/4;i++)
	{
		p1=(DWORD *)(pdword+4*i);
		p2=(DWORD *)(pbyte+4*i);
		*p2=htonl(*p1);
	}
}


void timeSync_log(const char *fmt,...)
{
//#if DUALSRV_DEBUG == 1
	char logFile[64];
	FILE *fp;
	time_t l_time;
	va_list ap;
	char buf[8192];
	struct tm *t;
	char timestr[64];
	
	l_time=time(NULL);
	t=localtime(&l_time);
	sprintf(logFile,"../log/SnmpTimeSync_%04d%02d%02d.log",t->tm_year+1900,t->tm_mon+1,t->tm_mday);
	fp=fopen(logFile,"a");
	if(fp!=NULL)
	{
		va_start(ap,fmt);
		vsprintf(buf,fmt,ap);
		sprintf(timestr,"%02d:%02d:%02d: ",t->tm_hour,t->tm_min,t->tm_sec);
		fputs(timestr,fp);
		fputs(buf,fp);
		fputs("\n",fp);
		fflush(fp);
		va_end(ap);
		fclose(fp);
	}
//#endif
}