/**************************************************/
/*Title:    snmpdebug.c                           */
/*Descr:    Debug Module of SNMP Agent            */
/*Author:   Liang Hanxi                           */
/*Create:   2002-4-1                              */
/*Modify:                                         */
/**************************************************/
#include	"./include/heartbeat.h"

static char				debug_buf[4096];
static char				asc_in[256];
static DWORD			title_id[20]={1,3,6,1,4,1,1373,1,3,2,3,1,2,13,8,1};

//private function
BYTE					snmpDebugFull = 0;
static snmp_filter		SnmpFilter[8];
static BYTE				SnmpFilterIndex = 0;
static DWORD			debug_mask = SNMP_DEBUG_MASK;
extern snmp_csta		SnmpCsta[96];
extern heartbeat_shm	*HbShm;
static char				Type_Name[9][16] = {"Get", "GetNext"
, "Response", "Set", "Trap-V1", "GetBulk", "Inform", "Trap-V2", "Report"};
static char				help_info[] = "Commands provided now:\r\n\
help    T001\r\n\
log all                         Output all debug information\r\n\
log none                        Turn off all information\r\n\
log error on/off                Show error information\r\n\
log noreg on/off                Alarm if oid is not registered\r\n\
log value on/off                Show value party of snmp message\r\n\
log alarm on/off                Show alarm information of platform\r\n\
log sys on/off                  Show system information\r\n\
log type cond1 (and cond2...)   Show message due to specified condition\r\n\
                                type should be snmp/trap/set/get/rsp\r\n\
                                One or more conditions could be taken:\r\n\
                                oid=x.x../ip=xx/local port=xx/remote port=xx\r\n\
                                For example:log trap oid=1.3.6.1.4.1373 and ip=172.18.98.1\r\n\
list register                   List all registered oid\r\n\
list status                     List system status\
";

int snmp_filter_msg(snmp_pdu *pMsg, snmp_addr *pAddr);
extern int Str2Oid(DWORD *pOid, char *pStr, BYTE maxLen);
extern void snmp_readpara();
extern void init_engine_para();

void snmp_debug_setup()
{
	DWORD				asc_id[20]={1,3,6,1,4,1,1373,1,1,2,3,1,2,13,4};
	DWORD				ascin_id[20]={1,3,6,1,4,1,1373,1,1,2,3,1,2,13,3};
	DWORD				status_id[20]={1,3,6,1,4,1,1373,1,1,2,3,1,2,13,1};
	DWORD				name_id[20]={1,3,6,1,4,1,1373,1,1,2,3,1,2,13,2};

	static  BYTE		debug_status=1;

	debug_set_response(15,asc_id, (BYTE *)debug_buf,1);
	debug_set_response(15,ascin_id, (BYTE *)asc_in,1);
	debug_set_response(15,status_id,&debug_status,1);
	debug_set_response(15,name_id, (BYTE *)SnmpVer, strlen(SnmpVer));
}

void snmp_log(char *info)
{
	if(strlen(debug_buf) + strlen(info) > 4096)
	{
		snmpDebugFull = 1;
		return;
	}

	strncat(debug_buf, info, 4094);
	strcat(debug_buf, "\r\n");
	return;
}

int snmp_filter_msg(snmp_pdu *pMsg, snmp_addr *pAddr)
{
	int			i;
	for(i = 0; i < SnmpFilterIndex % 9; i++)
	{
		if(SnmpFilter[i].type != pMsg->pdu_type && pMsg->pdu_type != 0xFF)
			continue;
		if(SnmpFilter[i].flag & 0x01)
		{
			if(SnmpFilter[i].ip != pAddr->remote_ip)
				continue;
		}
		if(SnmpFilter[i].flag & 0x02)
		{
			if(memcmp(SnmpFilter[i].oid, pMsg->var[0].oid, SnmpFilter[i].oidlen * 4) != 0)
				continue;
		}
		if(SnmpFilter[i].flag & 0x04)
		{
			if(SnmpFilter[i].local_port != pAddr->local_port)
				continue;
		}
		if(SnmpFilter[i].flag & 0x08)
		{
			if(SnmpFilter[i].remote_port != pAddr->remote_port)
				continue;
		}
		return 1;
	}
	return 0;
}

void snmp_debug(DWORD mask, const char *fmt, ...)
{
	va_list				ap;
	char				buf[1024];
	
	if((mask & debug_mask) == 0 || snmpDebugFull)
		return;

	if(mask & SNMPDB_ERR)
		strcat(debug_buf, "\33[31m");

	va_start(ap, fmt);
	vsprintf(buf, fmt, ap);
	va_end(ap);
	strcat(buf,"\33[37m");
	snmp_log(buf);
}

void snmp_showbuf(DWORD mask, BYTE *buf, int len)
{
	int			i = 0, j = 0, linemax = 24;
	char		info[1024];

	if((debug_mask & SNMPDB_VALUE) == 0  || (debug_mask & mask) == 0 || snmpDebugFull)
		return;
	
	if(len >= 256)
		len = 256;

	while(i * 24 < len)
	{
		if((linemax = len - 24 * i) > 24)
			linemax = 24;
		for(j = 0; j < linemax; j ++)
		{
			sprintf(info + 3 * j, "%02X ", buf[24 * i + j]);
		}
		snmp_log(info);
		i ++;
	}
}
int oid2str(char *pStr, DWORD *oid, BYTE oidlen)
{
	int		i;
	char	tmpstr[16];

	pStr[0] = 0;
	if(oidlen > OID_MAXLEN) oidlen = OID_MAXLEN;

	for(i = 0; i < oidlen - 1; i++)
	{
		sprintf(tmpstr, "%u.", oid[i]);
		strcat(pStr, tmpstr);
	}
	sprintf(tmpstr, "%u", oid[oidlen - 1]);
	strcat(pStr, tmpstr);
	return 1;
}

void snmp_logvalue(BYTE *msgbuf, short msglen)
{
	int						len, i = 0, j, linemax;
	char					info[1024];

	len = msglen % 256;
	while(i * 24 < len)
	{
		if((linemax = len - 24 * i) > 24)
			linemax = 24;
		for(j = 0; j < linemax; j ++)
		{
			sprintf(info + 3 * j, "%02X ", msgbuf[24 * i + j]);
		}
		snmp_log(info);
		i ++;
	}
}

void snmp_logmsg(DWORD mask, snmp_pdu *pdu, snmp_addr *addr)
{
	struct in_addr			inaddr;
	int						i = 0;
	char					info[1024], oidstr[64], desc[64] = "\0";

	if((debug_mask & mask) == 0 && snmp_filter_msg(pdu, addr) == 0)
		return;

	if(snmpDebugFull)
		return;

	if(mask & SNMPDB_ERR)
		strcat(debug_buf, "\33[31m");

	inaddr.s_addr = addr->remote_ip;
	if(mask & SNMPDB_IN)
		sprintf(desc, "\r\nlocal:%d <== %s:%d ", addr->local_port, inet_ntoa(inaddr), addr->remote_port);
	else if(mask & SNMPDB_OUT)
		sprintf(desc, "\r\nlocal:%d ==> %s:%d ", addr->local_port, inet_ntoa(inaddr), addr->remote_port);
	else
		sprintf(desc, "\r\nlocal:%d <=> %s:%d ", addr->local_port, inet_ntoa(inaddr), addr->remote_port);

	sprintf(info, "%sType=%s, RID=%u, Error=%d, Bind=%d\33[37m", desc, Type_Name[pdu->pdu_type], pdu->request_id
		, pdu->error_status, pdu->var_num);
	snmp_log(info);

	for(i = 0; i < pdu->var_num % 16; i++)
	{
		oid2str(oidstr, pdu->var[i].oid, pdu->var[i].oidlen);
		sprintf(info, "oid[%d]=%s, vartype=%02x, msglen=%d", i, oidstr, pdu->var[i].vartype, pdu->var[i].msglen);
		snmp_log(info);

		if((debug_mask & SNMPDB_VALUE) == 0)
			return;
		snmp_logvalue(pdu->var[i].msg, pdu->var[i].msglen);
	}
	
}

static int get_word(char *pWord, char *pInStr, BYTE max)
{
	char			*pStart = pInStr, *pCh = NULL;
	
	while(*pStart == ' ' || *pStart == '\t')
		pStart ++;

	strncpy(pWord, pStart, max);
	pCh = strchr(pWord, ' ');
	if(pCh != NULL)
		*pCh = 0;
	return 1;
}

static int parsecond(char *cmdstr, BYTE type)
{
	char		*pKey = cmdstr, *pEQ, info[256], tmpStr[64], valStr[32];

	if(SnmpFilterIndex >= 8)
	{
		snmp_log("only 8 pieces of condition can be set");
		return 0;
	}

	sprintf(info, "type = 0x%02X", type);
	SnmpFilter[SnmpFilterIndex].type = type;
	SnmpFilter[SnmpFilterIndex].flag = 0;

	if((pKey = strstr(cmdstr, "ip")) != NULL && (pEQ = strchr(pKey, '=')) != NULL)
	{
		get_word(valStr, pEQ + 1, 32);
		SnmpFilter[SnmpFilterIndex].ip = inet_addr(valStr);
		sprintf(tmpStr, " and ip = %s", valStr);
		strcat(info, tmpStr);
		SnmpFilter[SnmpFilterIndex].flag |= 0x01;
	}
	if((pKey = strstr(cmdstr, "oid")) != NULL && (pEQ = strchr(pKey, '=')) != NULL)
	{
		get_word(valStr, pEQ + 1, 32);
		if(SnmpFilter[SnmpFilterIndex].flag > 0) strcat(info, " and ");
		sprintf(tmpStr, " and oid = %s", valStr);
		strcat(info, tmpStr);
		SnmpFilter[SnmpFilterIndex].oidlen = Str2Oid(SnmpFilter[SnmpFilterIndex].oid, valStr, OID_MAXLEN) % OID_MAXLEN;
		SnmpFilter[SnmpFilterIndex].flag |= 0x02;
	}
	if((pKey = strstr(cmdstr, "local port")) != NULL && (pEQ = strchr(pKey, '=')) != NULL)
	{
		get_word(valStr, pEQ + 1, 32);
		SnmpFilter[SnmpFilterIndex].local_port = atoi(valStr);
		if(SnmpFilter[SnmpFilterIndex].flag > 0) strcat(info, " and ");
		sprintf(tmpStr, " and local port = %d", SnmpFilter[SnmpFilterIndex].local_port);
		strcat(info, tmpStr);
		SnmpFilter[SnmpFilterIndex].flag |= 0x04;
	}
	if((pKey = strstr(cmdstr, "remote port")) != NULL && (pEQ = strchr(pKey, '=')) != NULL)
	{
		get_word(valStr, pEQ + 1, 32);
		SnmpFilter[SnmpFilterIndex].remote_port = atoi(valStr);
		if(SnmpFilter[SnmpFilterIndex].flag > 0) strcat(info, " and ");
		sprintf(tmpStr, " and remote port = %d", SnmpFilter[SnmpFilterIndex].remote_port);
		strcat(info, tmpStr);
		SnmpFilter[SnmpFilterIndex].flag |= 0x08;
	}

	SnmpFilterIndex ++;
	snmp_log(info);
	snmp_log("command OK");
	return 1;
}

void snmp_debug_timer()
{
	BYTE			npage, nline;
	char			*cmdstr = asc_in + 1;
	if(strlen(asc_in) <= 1)
		return;
	debug_buf[0] = '\0';
	npage = asc_in[0] - 1;

	if(npage > 0)
	{
		nline = atoi(asc_in + 1);
		switch(npage)
		{
		case 1:		//csta
			snmp_debug_csta(1,nline);
			break;
		}
		asc_in[0]='\0';
		return;
	}

	asc_in[0]='\0';
	if(strstr(cmdstr, "help") != NULL || strstr(cmdstr, "?") != NULL)
	{
		snmp_log(help_info);
		return;
	}
	else if(strstr(cmdstr, "log all") != NULL)
	{
		SnmpFilterIndex = 0;
		debug_mask = 0xFFFFFFFF;
	}
	else if(strstr(cmdstr, "log none") != NULL)
	{
		SnmpFilterIndex = 0;
		debug_mask = 0;
	}
	else if(strstr(cmdstr, "log error on") != NULL)
		debug_mask |= SNMPDB_ERR;
	else if(strstr(cmdstr, "log error off") != NULL)
		debug_mask &= (~SNMPDB_ERR);
	else if(strstr(cmdstr, "log onreg on") != NULL)
		debug_mask |= SNMPDB_NOREG;
	else if(strstr(cmdstr, "log onreg off") != NULL)
		debug_mask &= (~SNMPDB_NOREG);
	else if(strstr(cmdstr, "log value on") != NULL)
		debug_mask |= SNMPDB_VALUE;
	else if(strstr(cmdstr, "log value off") != NULL)
		debug_mask &= (~SNMPDB_VALUE);
	else if(strstr(cmdstr, "log alarm on") != NULL)
		debug_mask |= SNMPDB_ALARM;
	else if(strstr(cmdstr, "log alarm off") != NULL)
		debug_mask &= (~SNMPDB_ALARM);
	else if(strstr(cmdstr, "log mib on") != NULL)
		debug_mask |= SNMPDB_MIB;
	else if(strstr(cmdstr, "log mib off") != NULL)
		debug_mask &= (~SNMPDB_MIB);
	else if(strstr(cmdstr, "log sys on") != NULL)
		debug_mask |= SNMPDB_SYS;
	else if(strstr(cmdstr, "log sys off") != NULL)
		debug_mask &= (~SNMPDB_SYS);
	else if(strstr(cmdstr, "log snmp") != NULL)
	{
		parsecond(cmdstr + 8, 0xFF);
		return;
	}
	else if(strstr(cmdstr, "log get") != NULL)
	{
		parsecond(cmdstr + 7, 0);
		return;
	}
	else if(strstr(cmdstr, "log set") != NULL)
	{
		parsecond(cmdstr + 7, 3);
		return;
	}
	else if(strstr(cmdstr, "log rsp") != NULL)
	{
		parsecond(cmdstr + 7, 2);
		return;
	}
	else if(strstr(cmdstr, "log trap") != NULL)
	{
		parsecond(cmdstr + 8, 7);
		return;
	}
	else if(strstr(cmdstr, "reload") != NULL)
	{
		snmp_readpara();
		init_engine_para();
		snmp_log("Command OK");

		return;
	}
	else
	{
		snmp_log("Invalid command/parameter(s).");
		return;
	}
	
	snmp_log("Command OK");
	return;
}

void snmp_debug_info(BYTE npage, BYTE nline, BYTE *pt, BYTE len)
{
	DWORD	oid[20]={1,3,6,1,4,1,1373,1,1,2,3,1,2,13,5,2,2};
	oid[14] = 5 + npage;
	oid[15] = 2 + nline;
	debug_set_response(17, oid, pt, len);
}

/*-----------------------------------------------*/
/*-------------------CSTA------------------------*/
/*-----------------------------------------------*/
void snmp_debug_csta(BYTE npage,int instance)
{
	char			title[256];
	snmp_csta		*pcsta;

	instance=instance%96;
	pcsta=&SnmpCsta[instance];

	sprintf(title,"\tSNMP-%s\tPage %02d\t\tMIB-CSTA(ID:1 Instance:%d)\r\n\r\n"\
								"trap in\r\n"\
								"trap out\r\n"\
								"set in\r\n"\
								"set out\r\n"\
								"get in\r\n"\
								"get out\r\n"\
								"rsp in\r\n"\
								"rsp out\r\n"\
								"fail to parse\r\n"\
								"OID Not registered\r\n"\
								"fail to build\r\n", SnmpVer, npage, instance);

	title_id[14]=5+npage;
	debug_set_response(16,title_id, (BYTE *)title,strlen(title));

	snmp_debug_info(npage,0,(BYTE *)&pcsta->trap_in,4);
	snmp_debug_info(npage,1,(BYTE *)&pcsta->trap_out,4);
	snmp_debug_info(npage,2,(BYTE *)&pcsta->set_in,4);
	snmp_debug_info(npage,3,(BYTE *)&pcsta->set_out,4);
	snmp_debug_info(npage,4,(BYTE *)&pcsta->get_in,4);
	snmp_debug_info(npage,5,(BYTE *)&pcsta->get_out,4);
	snmp_debug_info(npage,6,(BYTE *)&pcsta->rsp_in,4);
	snmp_debug_info(npage,7,(BYTE *)&pcsta->rsp_out,4);
	snmp_debug_info(npage,8,(BYTE *)&pcsta->fail_parse,4);
	snmp_debug_info(npage,9,(BYTE *)&pcsta->not_register,4);
	snmp_debug_info(npage,10,(BYTE *)&pcsta->fail_build,4);
	
}

void snmp_debug_hb(BYTE npage)
{
	char			title[512];
	sprintf(title,"\tSNMP-%s\tPage %02d\t\tHeartBeat\r\n"\
								"\r\n"\
								"subsys id\r\n"\
								"LED\r\n"\
								"Component 0\r\n"\
								"\r\n"\
								"Component 1\r\n"\
								"\r\n"\
								"Component 2\r\n"\
								"\r\n"\
								"Component 3\r\n"\
								"\r\n"\
								"Component 4\r\n"\
								"\r\n"\
								"Component 5\r\n"\
								"\r\n"\
								"Component 6\r\n"\
								"\r\n"\
								"alarm num\r\n"\
								"HB message\r\n\r\n", SnmpVer, npage);

	title_id[14]=5+npage;
	
	debug_set_response(16,title_id, (BYTE *)title,strlen(title));

	snmp_debug_info(npage,0,(BYTE *)&HbShm->sys_id,2);
	snmp_debug_info(npage,1,(BYTE *)HbShm->led,LED_NUM);
	snmp_debug_info(npage,2,(BYTE *)&HbShm->component[0],20);
	snmp_debug_info(npage,3,(BYTE *)&HbShm->component[0]+20,20);
	snmp_debug_info(npage,4,(BYTE *)&HbShm->component[1],20);
	snmp_debug_info(npage,5,(BYTE *)&HbShm->component[1]+20,20);
	snmp_debug_info(npage,6,(BYTE *)&HbShm->component[2],20);
	snmp_debug_info(npage,7,(BYTE *)&HbShm->component[2]+20,20);
	snmp_debug_info(npage,8,(BYTE *)&HbShm->component[3],20);
	snmp_debug_info(npage,9,(BYTE *)&HbShm->component[3]+20,20);
	snmp_debug_info(npage,10,(BYTE *)&HbShm->component[4],20);
	snmp_debug_info(npage,11,(BYTE *)&HbShm->component[4]+20,20);
	snmp_debug_info(npage,12,(BYTE *)&HbShm->component[5],20);
	snmp_debug_info(npage,13,(BYTE *)&HbShm->component[5]+20,20);
	snmp_debug_info(npage,14,(BYTE *)&HbShm->component[6],20);
	snmp_debug_info(npage,15,(BYTE *)&HbShm->component[6]+20,20);

	snmp_debug_info(npage,16,(BYTE *)&HbShm->alarm_num,1);
	snmp_debug_info(npage,17,(BYTE *)&HbShm->msg,20);
	snmp_debug_info(npage,18,(BYTE *)&HbShm->msg+20,20);
	snmp_debug_info(npage,19,(BYTE *)&HbShm->msg+40,20);
	snmp_debug_info(npage,20,(BYTE *)&HbShm->msg+60,20);
	snmp_debug_info(npage,21,(BYTE *)&HbShm->msg+80,20);
	
}



