/****************************************************************
 ****************************************************************
 **                                                            **
 **    (C)Copyright 2005-2006, American Megatrends Inc.        **
 **                                                            **
 **            All Rights Reserved.                            **
 **                                                            **
 **        6145-F, Northbelt Parkway, Norcross,                **
 **                                                            **
 **        Georgia - 30071, USA. Phone-(770)-246-8600.         **
 **                                                            **
 ****************************************************************
 ****************************************************************/
/*****************************************************************
 *
 * RMCP.c
 * RMCP Message Handler
 *
 * Author: Govind Kothandapani <govindk@ami.com>
 *       : Bakka Ravinder Reddy <bakkar@ami.com>
 *
 *****************************************************************/
#include "com_Message.h"
#include "com_IPMIDefs.h"
#include "Session.h"
#include "LANIfc.h"
#include "MD.h"
#include "RMCP.h"
#include "RMCP+.h"
#include "main.h"
#include "MD5_128.h"
#include <string.h>
#include "BmcType.h"
#include "AuthCode.h"


/*** Local definitions ***/
#define RMCP_VERSION                6
#define IPMI_MESSAGE_CLASS          7
#define PRESENCE_PING_MSGTYPE       0x80
#define RMCP_VERSION                6

#define AMI_CMD_NETFN_LUN           (((0x2E | 1) << 2) | 0x00)
#define AMI_CMD_12                  0x12
#define PING_IPMI_15_SUPPORT        1
#define PING_IPMI_20_SUPPORT        2
#define MAX_AUTH_CODE_SIZE          12
#define INIT_VECTOR_SIZE            16
#define INTEGRITY_MASK              BIT6
#define CONFIDENT_MASK              BIT7

#define PAYLOAD_RSSP_OS_REQ         0x10
#define PAYLOAD_RSSP_OS_RES         0x11
#define PAYLOAD_RAKP_MSG1           0x12
#define PAYLOAD_RAKP_MSG2           0x13
#define PAYLOAD_RAKP_MSG3           0x14
#define PAYLOAD_RAKP_MSG4           0x15

// /*** Prototype Declaration ***/
static int ProcIPMIReq (  SessionInfo_T*  pSessionInfo, uint8_t Payload, MsgPkt_T *pReq, MsgPkt_T *pRes);
static uint8_t  ValidateRMCPHdr    (  RMCPHdr_T* pRMCPHdr);
// static bool  ValidateSessionHdr (uint32_t SessionID, uint32_t SeqNo );
static uint8_t ProcessPingMsg     (  RMCPHdr_T* pRMCPReq,
 								   RMCPHdr_T* pRMCPRes );
static uint8_t  ValidateAuthCode   (  uint8_t* pAuthCode,   uint8_t* pPassword,
 								   SessionHdr_T* pSessionHdr,
 								   IPMIMsgHdr_T* pIPMIMsg);
// static int   Proc20Payload      (  RMCPHdr_T* pRMCPReq,
// 								   RMCPHdr_T* pRMCPRes, MiscParams_T *pParams, uint8_t Channel );

/*** Local typedefs ***/
/**
 * @struct PreSessionCmd_T
 * @brief Pre-session command entry.
**/
typedef struct
{
	uint8_t   NetFn;
	uint8_t   Cmd;
} PreSessionCmd_T;

/**
 * @brief Message Payload Handler function.
 * @param pReq   - Request message.
 * @param ReqLen - Request length.
 * @param pRes   - Response message.
 * @return 0 if success, -1 if error.
**/
typedef int (*pPayloadHndlr_T) (  uint8_t* pReq, uint8_t ReqLen,
								  uint8_t* pRes, uint8_t Channel );

/**
 * @struct PayloadTbl_T;
 * @brief Payload Table structure.
**/
typedef struct
{
	uint8_t           Payload;
	pPayloadHndlr_T PayloadHndlr;
} PayloadTbl_T;


// static const PayloadTbl_T m_PayloadTbl [] =
// {
// 	 /*  Payload              Handler           */
// 	{PAYLOAD_RSSP_OS_REQ,   RSSPOpenSessionReq  },
// 	{PAYLOAD_RAKP_MSG1,     RAKPMsg1            },
// 	{PAYLOAD_RAKP_MSG3,     RAKPMsg3            },
// };

// /* Pre-Session establishment commands */
// static const PreSessionCmd_T m_PreSessionCmdsTbl[] =
// {
// 	{ NETFN_APP,    CMD_GET_CH_AUTH_CAP },
// 	{ NETFN_APP,    CMD_GET_SESSION_CHALLENGE },
// 	{ NETFN_APP,    CMD_GET_DEV_GUID },
// 	{ NETFN_APP,    CMD_GET_CH_CIPHER_SUITES },
// 	{ NETFN_APP,    CMD_GET_SYSTEM_GUID },
// 	{ NETFN_SENSOR, CMD_PET_ACKNOWLEDGE},
// };

// /**
//  * @struct IPMIAuditMaskTbl_T;
//  * @brief  Maps Audit Event types to their bitmask in configuration.
// **/
// typedef struct
// {
// 	uint8_t EventType;
// 	uint8_t EventMask;
// }IPMIAuditMaskTbl_T;

// static const IPMIAuditMaskTbl_T m_IPMIAuditMaskMap[] =
// {
// 	{ EVENT_LOGIN,           0x0 },
// 	{ EVENT_LOGOUT,          0x1 },
// 	{ EVENT_AUTO_LOGOUT,     0x2 },
// 	{ EVENT_LOGIN_FAILURE,   0x3 },
// };


// int RmcpSeqNumValidation(SessionInfo_T* pSessionInfo, uint32_t SessionSeqNum, IPMIMsgHdr_T* pIPMIMsgReq)
// {
// 	uint32_t  SeqTrac[SIXTEEN_COUNT_WINDOW_LEN];
// 	bool    TrackRollOver       = FALSE;
// 	uint32_t  TrackRollOverSeq    = SEQNUM_ROLLOVER;
// 	int     i;
	
// 	if((pIPMIMsgReq->Cmd != CMD_ACTIVATE_SESSION) ||
// 	   ((pIPMIMsgReq->Cmd == CMD_ACTIVATE_SESSION) &&
// 	   (SessionSeqNum != 0)))
// 	{
// 		if( pSessionInfo->InboundSeq == SessionSeqNum)
// 			return -1;

// 		 if((pSessionInfo->InboundSeq < (SEQNUM_ROLLOVER - EIGHT_COUNT_WINDOW_LEN)) && (pSessionInfo->InboundSeq > EIGHT_COUNT_WINDOW_LEN))
// 		 {
// 			if(SessionSeqNum < pSessionInfo->InboundSeq)
// 			{
// 				if((pSessionInfo->InboundSeq -SessionSeqNum) > EIGHT_COUNT_WINDOW_LEN)
// 				{
// 				   return -1;
// 				}
// 				else
// 				{
// 					for(i=0;i<EIGHT_COUNT_WINDOW_LEN;i++)
// 					{
// 						if(SessionSeqNum == pSessionInfo->InboundTrac[i])
// 						{
// 							if(((1 << i) & pSessionInfo->InboundRecv) != 0)
// 							{
// 								 return -1;
// 							}
// 							else
// 							{
// 								 pSessionInfo->InboundRecv |= (1<<i);
// 							}
// 						}
// 					}
// 				}
// 			}
// 			else
// 			{
// 				if((SessionSeqNum - pSessionInfo->InboundSeq) > EIGHT_COUNT_WINDOW_LEN)
// 				{
// 					return -1;
// 				}

// 				_fmemcpy((uint8_t *)SeqTrac,(uint8_t *)pSessionInfo->InboundTrac,(sizeof(uint32_t) * EIGHT_COUNT_WINDOW_LEN));

// 				for(i=0; i < (SessionSeqNum - pSessionInfo->InboundSeq); i++)
// 				{
// 					pSessionInfo->InboundTrac[i] = SessionSeqNum - (i+1);
// 				}

// 				pSessionInfo->InboundRecv = pSessionInfo->InboundRecv << (SessionSeqNum - pSessionInfo->InboundSeq);
// 				pSessionInfo->InboundRecv |= (1 << ((SessionSeqNum - pSessionInfo->InboundSeq)-1));

// 				_fmemcpy((uint8_t *)&pSessionInfo->InboundTrac[SessionSeqNum - pSessionInfo->InboundSeq],
// 								(uint8_t *)&SeqTrac[0],
// 								(sizeof(uint32_t) *(EIGHT_COUNT_WINDOW_LEN - (SessionSeqNum - pSessionInfo->InboundSeq))));
// 				pSessionInfo->InboundSeq = SessionSeqNum;
// 			}
// 		}
// 		else if((pSessionInfo->InboundSeq  < EIGHT_COUNT_WINDOW_LEN)
// 					|| (pSessionInfo->InboundSeq  > (SEQNUM_ROLLOVER -EIGHT_COUNT_WINDOW_LEN))) /* Checking for Roll over condition */
// 		{
// 			if(SessionSeqNum < pSessionInfo->InboundSeq)
// 			{
// 				if(!((((pSessionInfo->InboundSeq -SessionSeqNum) <= EIGHT_COUNT_WINDOW_LEN) &&
// 				   (((SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1) >= EIGHT_COUNT_WINDOW_LEN )) ||
// 				   ((((SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1) <= EIGHT_COUNT_WINDOW_LEN ) &&
// 					   (pSessionInfo->InboundSeq -SessionSeqNum) >= EIGHT_COUNT_WINDOW_LEN)))
// 				{
// 				  return -1;
// 				}
// 				else
// 				{
// 					if((pSessionInfo->InboundSeq -SessionSeqNum) <= EIGHT_COUNT_WINDOW_LEN)
// 					{
// 						for(i=0;i<EIGHT_COUNT_WINDOW_LEN;i++)
// 						{
// 							if(SessionSeqNum == pSessionInfo->InboundTrac[i])
// 							{
// 								if(((1 << i) & pSessionInfo->InboundRecv) != 0)
// 								{
// 									return -1;
// 								}
// 								else
// 								{
// 									pSessionInfo->InboundRecv |= (1<<i);
// 								}
// 							}
// 						}
// 					 }
// 					else if(((SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1) <= EIGHT_COUNT_WINDOW_LEN )
// 					{
// 						_fmemcpy((uint8_t *)SeqTrac,(uint8_t *)pSessionInfo->InboundTrac,(sizeof(uint32_t) * EIGHT_COUNT_WINDOW_LEN));

// 						for(i=0; i < ((SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1); i++)
// 						{
// 							if(((SessionSeqNum - (i+1)) != 0) && (TrackRollOver == FALSE))
// 								pSessionInfo->InboundTrac[i] = SessionSeqNum - (i+1);
// 							else if(((SessionSeqNum - (i+1)) == 0) && (TrackRollOver == FALSE))
// 							{
// 								pSessionInfo->InboundTrac[i] = SessionSeqNum - (i+1);
// 								TrackRollOver = TRUE;
// 							}
// 							else if(TrackRollOver ==  TRUE)
// 							{
// 								pSessionInfo->InboundTrac[i] = TrackRollOverSeq;
// 								TrackRollOverSeq--;
// 							}
// 						}
// 						TrackRollOverSeq = SEQNUM_ROLLOVER;
// 						TrackRollOver = FALSE;

// 						pSessionInfo->InboundRecv = pSessionInfo->InboundRecv << ((SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1);
// 						pSessionInfo->InboundRecv |= (1 << (((SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1) -1));

// 						_fmemcpy((uint8_t *)&pSessionInfo->InboundTrac[(SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1],
// 						(uint8_t *)&SeqTrac[0],
// 						(sizeof(uint32_t) *(EIGHT_COUNT_WINDOW_LEN - ((SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1))));
// 						pSessionInfo->InboundSeq = SessionSeqNum;
// 					}
// 				}
// 			}
// 			else if(SessionSeqNum > pSessionInfo->InboundSeq)
// 			{
// 				if(!((((SessionSeqNum -pSessionInfo->InboundSeq) <= EIGHT_COUNT_WINDOW_LEN) &&
// 				   (((SEQNUM_ROLLOVER - SessionSeqNum) + pSessionInfo->InboundSeq+1) >= EIGHT_COUNT_WINDOW_LEN )) ||
// 				   ((((SEQNUM_ROLLOVER - SessionSeqNum) + pSessionInfo->InboundSeq+1) <= EIGHT_COUNT_WINDOW_LEN ) &&
// 					   (SessionSeqNum-pSessionInfo->InboundSeq) >= EIGHT_COUNT_WINDOW_LEN)))
// 				{
// 					return -1;
// 				}
// 				else
// 				{
// 					if((SessionSeqNum  - pSessionInfo->InboundSeq) <= EIGHT_COUNT_WINDOW_LEN)
// 					{
// 						_fmemcpy((uint8_t *)SeqTrac,(uint8_t *)pSessionInfo->InboundTrac,(sizeof(uint32_t) * EIGHT_COUNT_WINDOW_LEN));
// 						for(i=0;i<(SessionSeqNum  - pSessionInfo->InboundSeq) ;i++)
// 						{
// 							if(((SessionSeqNum - (i+1)) != 0) && (TrackRollOver == FALSE))
// 							{
// 								pSessionInfo->InboundTrac[i] = SessionSeqNum - (i+1);
// 							}
// 							else if(((SessionSeqNum - (i+1)) == 0) && (TrackRollOver == FALSE))
// 							{
// 								pSessionInfo->InboundTrac[i] = SessionSeqNum - (i+1);
// 								TrackRollOver = TRUE;
// 							}
// 							else if(TrackRollOver ==  TRUE)
// 							{
// 								pSessionInfo->InboundTrac[i] = TrackRollOverSeq;
// 								TrackRollOverSeq--;
// 							}
// 						}
// 						TrackRollOverSeq = SEQNUM_ROLLOVER;
// 						TrackRollOver = FALSE;

// 						pSessionInfo->InboundRecv = pSessionInfo->InboundRecv << (SessionSeqNum  - pSessionInfo->InboundSeq);
// 						pSessionInfo->InboundRecv |= (1 << ((SessionSeqNum  - pSessionInfo->InboundSeq) -1));

// 						_fmemcpy((uint8_t *)&pSessionInfo->InboundTrac[SessionSeqNum  - pSessionInfo->InboundSeq],
// 						(uint8_t *)&SeqTrac[0],
// 						(sizeof(uint32_t) *(EIGHT_COUNT_WINDOW_LEN - (SessionSeqNum - pSessionInfo->InboundSeq))));
// 						pSessionInfo->InboundSeq = SessionSeqNum;
// 					}
// 					else if(((SEQNUM_ROLLOVER -SessionSeqNum) + pSessionInfo->InboundSeq+1) <= EIGHT_COUNT_WINDOW_LEN)
// 					{
// 						for(i=0;i<EIGHT_COUNT_WINDOW_LEN;i++)
// 						{
// 							if(SessionSeqNum == pSessionInfo->InboundTrac[i])
// 							{
// 								if(((1 << i) & pSessionInfo->InboundRecv) != 0)
// 								{
// 									return -1;
// 								}
// 								else
// 								{
// 									pSessionInfo->InboundRecv |= (1<<i);
// 								}
// 							}
// 						}

// 					}
// 				}
// 			}
// 		 }
// 	}

// 	return 0;
// }

/*-------------------------------------------
 * ProcessRMCPReq
 *-------------------------------------------*/
uint32_t
ProcessRMCPReq( RMCPHdr_T* pRMCPReq,  RMCPHdr_T* pRMCPRes)
{
	SessionInfo_T*  pSessionInfo = NULL;
	IPMIMsgHdr_T*   pIPMIMsgReq;
	IPMIMsgHdr_T*   pIPMIMsgRes;
	uint8_t*          pReqMsgAuthCode;
	uint8_t*          pResMsgAuthCode;
	SessionHdr_T*   pReqSessionHdr = ( SessionHdr_T*)(pRMCPReq + 1);
	SessionHdr_T*   pResSessionHdr = ( SessionHdr_T*)(pRMCPRes + 1);
	uint8_t           IPMIMsgLen;
	uint32_t          SessionID;
	uint32_t          ResLen, IPMIMsgResLen;
	MsgPkt_T	Req,Res;

	/* Validate RMCP Header */
	if (TRUE != ValidateRMCPHdr(pRMCPReq))
	{
		printf ("RMCP.c : RMCP header validation failed\r\n");
		return 0;
	}

	/* If RMCP Ping, process it seperately */
	if (pRMCPReq->MsgClass == 0x06)
	{
		return ProcessPingMsg (pRMCPReq, pRMCPRes);
	}

	/* Process IPMI 2.0 Separately */
#if IPMI20_SUPPORT == 1
//	if (RMCP_PLUS_FORMAT == pReqSessionHdr->AuthType)
//	{
//		ResLen = Proc20Payload (pRMCPReq, pRMCPRes);
//	}
//	else
#endif
	{
		SessionID             = pReqSessionHdr->SessionID;

		/* Get Session Information */
		pSessionInfo = getSessionInfo (SESSION_ID_INFO, &SessionID);
	
		if (0 == pReqSessionHdr->AuthType)
		{
			IPMIMsgLen  = (uint8_t) (*(( uint8_t*)(pReqSessionHdr + 1)));

			pIPMIMsgReq = ( IPMIMsgHdr_T*) ((( uint8_t*)(pReqSessionHdr + 1)) +
						  sizeof (IPMIMsgLen));
			pIPMIMsgRes = ( IPMIMsgHdr_T*) ((( uint8_t*)(pResSessionHdr + 1)) +
						  sizeof (IPMIMsgLen));
		}
		else
		{
			pReqMsgAuthCode = (( uint8_t*)(pReqSessionHdr + 1));
			pResMsgAuthCode = (( uint8_t*)(pResSessionHdr + 1));
			IPMIMsgLen      = *(pReqMsgAuthCode + AUTH_CODE_LEN);
			pIPMIMsgReq     = ( IPMIMsgHdr_T*) (pReqMsgAuthCode + AUTH_CODE_LEN +
							  sizeof (IPMIMsgLen));
			pIPMIMsgRes     = ( IPMIMsgHdr_T*) (pResMsgAuthCode + AUTH_CODE_LEN +
							  sizeof (IPMIMsgLen));
			
			if (TRUE != ValidateAuthCode (pReqMsgAuthCode, g_BMCInfo.pUserInfo->UserPassword,
										  pReqSessionHdr, pIPMIMsgReq))
			{
				printf("Password error!\n");
				return 0;
			}
			//TODO:pSessionInfo->Password到底是在哪里赋值的?在这里可以吗?
			//memcpy(pSessionInfo->Password,g_BMCInfo.pUserInfo->UserPassword,MAX_PASSWORD_LEN);
		}

		/* Frame the Message Packet for Message Handler */
		Req.Param	  = PARAM_IFC;
		Req.Cmd       = pIPMIMsgReq->Cmd;
		Req.NetFnLUN  = pIPMIMsgReq->NetFnLUN;
		Req.SessionID = SessionID;
		Req.SessionType = LAN_SESSION_TYPE;
		Req.Channel 	= LAN_RMCP_CHANNEL;
		
		//UpdateGetMsgTime( &pBMCInfo->LANConfig.MsgReq,IfcType, BMCInst);
		Req.Size = IPMIMsgLen;
		memcpy(Req.Data, ( uint8_t*) pIPMIMsgReq, Req.Size);

		/* Post Msg to MsgHndlr and Get Res */
		if (0 != ProcIPMIReq (pSessionInfo, PAYLOAD_IPMI_MSG, &Req, &Res))
		{
			return 0;
		}

		/* Fill Response data */
		memcpy (pRMCPRes, pRMCPReq, sizeof (RMCPHdr_T) + sizeof (SessionHdr_T));

		/* Fill Authentication Code */
		if (0 != pReqSessionHdr->AuthType)
		{
			pResMsgAuthCode = ( uint8_t*)(pResSessionHdr + 1);
			pIPMIMsgRes     = ( IPMIMsgHdr_T*)(( uint8_t*)(pResSessionHdr + 1) +
							  AUTH_CODE_LEN + sizeof (IPMIMsgLen));
			IPMIMsgResLen      = AUTH_CODE_LEN + sizeof (IPMIMsgLen) + Res.Size;
			/* Fill IPMI Message */
			memcpy (pIPMIMsgRes, Res.Data, Res.Size);
			*(pResMsgAuthCode + AUTH_CODE_LEN) = Res.Size;

//			ComputeAuthCode ((uint8_t*)g_BMCInfo.pUserInfo->UserPassword, pResSessionHdr, pIPMIMsgRes,
//							 pResMsgAuthCode, MULTI_SESSION_CHANNEL);
		}
		else
		{
			pIPMIMsgRes = ( IPMIMsgHdr_T*)(( uint8_t*)(pResSessionHdr + 1) +
						  sizeof (IPMIMsgLen));
			IPMIMsgResLen  = Res.Size + sizeof (IPMIMsgLen);
			/* Fill IPMI Message */
			memcpy (pIPMIMsgRes, Res.Data, Res.Size);
			*(( uint8_t*) (pResSessionHdr + 1)) = Res.Size;
		}

//		if( (NETFN_APP == (pIPMIMsgReq->NetFnLUN >> 2)) && (CMD_GET_SESSION_CHALLENGE == pIPMIMsgReq->Cmd) && 
//			(CC_GET_SESSION_INVALID_USER == Res.Data[sizeof(IPMIMsgHdr_T)]) && (NULL == pSessionInfo) )
//		{
//			if ( 0 != AddLoginEvent( 0xFF, &pBMCInfo->LANConfig.MsgReq.Data[7], EVENT_LOGIN_FAILURE, BMCInst ))
//			{
//				TCRIT("Problem while adding Log record \n");
//			}
//		}
		ResLen = sizeof (RMCPHdr_T) + sizeof (SessionHdr_T) + IPMIMsgResLen;
	}

	return ResLen;
}

/**
 * @brief Process the IPMI request and prepare response.
 * @param pSessionInfo - Session information.
 * @param Payload     - Payload type.
 * @return 0 if success, -1 if error.
**/
int ProcIPMIReq (  SessionInfo_T*  pSessionInfo, uint8_t Payload, MsgPkt_T *pReq, MsgPkt_T *pRes)
{
//	ChannelInfo_T*      pChannelInfo;
//	int	RetVal = 0;

	//printf("ProcIPMIReq\n");
	/* Frame the Message Packet for Message Handler */
	pReq->Param     = PARAM_IFC;
	pReq->SrcQ		= gFd_LanResQ;
	
	if (PAYLOAD_IPMI_MSG == Payload)
	{
//		printf("\n\n===> Post to MsgHndlr\n");
		PostMsg (gFd_MsgHndlrIfc, pReq);
	}
   
	
		
	if ( GetMsg (gFd_LanResQ, pRes, DEFAULT_TIMEOUT) != 0)
	{
		//FillIPMIResFailure (pReq, pRes);
		printf("Warning: RMCP get message error!\n");
		return -1;
	}

//	printf("===> gFd_LanResQ Recv: ");
	// int i;
	// for(i=0;i<pRes->Size;i++)
	// 	printf("%#x ", pRes->Data[i]);
	// printf("\n");


	if (PARAM_NO_RESPONSE == pRes->Param)
	{
		printf ("RMCP.c : No response from message handler\n");
		return -1;
	}

	//printf("ProcIPMIReq get response: Param %#x, netfn %#x, cmd %#x, len %#x\n", pRes->Param, pRes->NetFnLUN, pRes->Cmd, pRes->Size);
	
	if (((pReq->NetFnLUN >> 2) == 0x06) && (pReq->Cmd  == 0x3A) &&			//Active Session , ipmi2.0 page 613
		(PAYLOAD_IPMI_MSG == Payload))
	{
		//TODO:
	}    

	/* If Request IPMI Message is Close Session */
	if (((pReq->NetFnLUN >> 2) == 0x06) && (pReq->Cmd  == 0x3C) &&			//close session
		(PAYLOAD_IPMI_MSG == Payload))
	{
		//TODO:
	}

	return 0;
}

/**
 * @brief Validate RMCP Header
 * @param pRMCPHdr - RMCP header.
 * @return TRUE if valid, FALSE if invalid.
**/
static uint8_t
ValidateRMCPHdr (  RMCPHdr_T* pRMCPHdr)
{
	/* If RMCP Packet is NULL */
	if (pRMCPHdr == NULL)
	{
		printf ("RMCP.c : RMCP Packet is NULL\n");
		return FALSE;
	}

	/* Verify RMCP Version */
	if (pRMCPHdr->Version != RMCP_VERSION)
	{
		printf ("RMCP.c : Invalid RMCP Version\n");
		return FALSE;
	}

	/* LOOK for RMCP MessageClass */
	if ((pRMCPHdr->MsgClass != IPMI_MESSAGE_CLASS) &&
		(pRMCPHdr->MsgClass != 0x06))
	{
		printf ("RMCP.c : Invalid Message Class\n");
		return FALSE;
	}

	return TRUE;
}

// /**
//  * @brief Validate session header.
//  * @param SessionID - Session ID.
//  * @param SeqNo    - Session Sequence Number.
//  * @return TRUE if valid, FALSE if invalid.
// **/
// static bool
// ValidateSessionHdr (uint32_t SessionID, uint32_t SeqNo )
// {
// 	   SessionInfo_T*   pSessionInfo;

// 	/* if its Pre Session commands  */
// 	if (0 == SessionID)
// 	{
// 		return TRUE;
// 	}

// 	pSessionInfo = getSessionInfo (SESSION_ID_INFO, &SessionID, BMCInst);
// 	if ( pSessionInfo == NULL)
// 	{
// 		return FALSE;
// 	}

// 	/* If packet is already received - drop the packet  */
// /*  if (ntohs(SeqNo) <= ntohs (CAST_32 (&pSessionInfo->InboundSeq)))
// 	{
// 		 IPMI_DBG_PRINT ("RMCP: Duplicate Seq No - Packet dropped\n");
// 		 return FALSE;
// 	}
// */

// 	/* inc the Sequence No  */

// 	return TRUE;
// }

/**
 * @brief Process RMCP Ping Message.
 * @param pRMCPReq - Request RMCP message.
 * @param pRMCPRes - Response RMCP message.
 * @return the response length.
**/
static uint8_t
ProcessPingMsg (  RMCPHdr_T* pRMCPReq,   RMCPHdr_T* pRMCPRes )
{
	  RMCPPingHdr_T* pReqPingHdr = (  RMCPPingHdr_T*)(pRMCPReq + 1);
	  RMCPPingHdr_T* pResPingHdr = (  RMCPPingHdr_T*)(pRMCPRes + 1);

	if (PRESENCE_PING_MSGTYPE != pReqPingHdr->MsgType) { return 0; }
	if((pReqPingHdr->IANANum[0]!=0x00)||(pReqPingHdr->IANANum[1]!=0x00)||
		 (pReqPingHdr->IANANum[2]!=0x11)||(pReqPingHdr->IANANum[3]!=0xBE)) 
	   { return 0; }

	/* Construct Response Header */
	memcpy (pResPingHdr, pReqPingHdr, sizeof (RMCPPingHdr_T));
	pResPingHdr->MsgType = 0x40;
	pResPingHdr->DataLen = 0x10;

	/* Fill Response Data */
	memset (pResPingHdr + 1, 0, pResPingHdr->DataLen);
	*((  uint8_t*)(pResPingHdr + 1) + 8) = 0x81;
	*((  uint8_t*)(pResPingHdr + 1) + 4) = PING_IPMI_15_SUPPORT;

#if IPMI20_SUPPORT == 1
//	*((  uint8_t*)(pResPingHdr + 1) + 4) |= PING_IPMI_20_SUPPORT;
#endif

	// /*Update the OEM IANA Number for DCMI Discovery (36465 = Data Center Manageability Forum,Spec .1.5)*/
	// if(g_corefeatures.dcmi_1_5_support == ENABLED)
	// {
	// 	if(pBMCInfo->IpmiConfig.DCMISupport == 1)
	// 	{
	// 		*((  uint8_t*)(pResPingHdr + 1) + 2) = 0x8E;
	// 		*((  uint8_t*)(pResPingHdr + 1) + 3) = 0x71;
	// 	}
	// }

	return (sizeof (RMCPHdr_T) + sizeof (RMCPPingHdr_T) + pResPingHdr->DataLen);
}


/**
 * @brief Validate Authentication Code
 * @param pAuthCode - Request authentication code.
 * @param pPassword - Password string.
 * @param pSessionHdr - Request Session header.
 * @param pIPMIMsg - Request IPMI message.
 * @return TRUE if valid, FALSE if invalid.
**/
static uint8_t
ValidateAuthCode (  uint8_t* pAuthCode,   uint8_t* pPassword,
				    SessionHdr_T* pSessionHdr,   IPMIMsgHdr_T* pIPMIMsg)
{
	uint8_t   ComputedAuthCode [AUTH_CODE_LEN];

	memset(ComputedAuthCode, 0, sizeof (ComputedAuthCode));

	ComputeAuthCode (pPassword, pSessionHdr, pIPMIMsg,
					 ComputedAuthCode, MULTI_SESSION_CHANNEL);

	// int i;
	// printf("pAuthCode: ");
	// for(i=0;i<AUTH_CODE_LEN;i++)
	// 	printf("%#x ", pAuthCode[i]);
	// printf("\n");
	// printf("pPassword: %s\n", pPassword);
	// printf("pComputeAuthCode: ");
	// for(i=0;i<AUTH_CODE_LEN;i++)
	// 	printf("%#x ", ComputedAuthCode[i]);
	// printf("\n");
	

	return (0 == memcmp (pAuthCode, ComputedAuthCode, AUTH_CODE_LEN));
}

 #if IPMI20_SUPPORT

// /*-------------------------------------------
//  * Frame20Payload
//  *-------------------------------------------*/
// int
// Frame20Payload (uint8_t PayloadType,   RMCPHdr_T* pRMCPPkt,
// 				  uint8_t* pPayload,  uint32_t PayloadLen,  
// 				SessionInfo_T* pSessionInfo )
// {
// 	   BMCInfo_t*       pBMCInfo        = &g_BMCInfo[BMCInst];
// 	  SessionHdr2_T*   pResSessionHdr  = (  SessionHdr2_T*)(pRMCPPkt + 1);
// 	  uint8_t*           pRes            = (  uint8_t*)(pResSessionHdr + 1);
// 	  uint8_t*           pConfHdr;
// 	  uint8_t*           pConfPayld;
// 	  uint8_t*           pIntPad;
// 	  uint8_t*           pResMsgAuthCode;
// 	uint8_t                   ConfPadLen, IntPadLen;
// 	INT16U                  ConfPayldLen, AuthCodeLen;
// 	int                     i, ResLen;
// 	unsigned int            seed = 1;

// 	/* Fill Session Hdr */
// 	pResSessionHdr->AuthType      = RMCP_PLUS_FORMAT;
// 	pResSessionHdr->PayloadType   = PayloadType;


// 	if (NULL == pSessionInfo)
// 	{
// 		pResSessionHdr->SessionID = 0;
// 		pResSessionHdr->SessionSeqNum = 0;
// 	}
// 	else
// 	{
// 		/* Response packets should send the Remote Console
// 		 * Session ID so the remote console can correctly
// 		 * match up the session with its own table of active
// 		 * session IDs. */
// 		pResSessionHdr->SessionID = pSessionInfo->RemConSessionID;

// 		/* Increment session sequence number */
// 		/* During RMCP Opensession , OutboundSeq initialized to 0 and but 0 is  reserved  */
// 		/* and also  When It reach 0xffffffff then It  become zero */
// 		if(0==pSessionInfo->OutboundSeq)
// 		{
// 			pSessionInfo->OutboundSeq=1;
// 		}
// 		pResSessionHdr->SessionSeqNum = htoipmi_u32(pSessionInfo->OutboundSeq++);
// 	}

// 	/* Fill Payload and Do Encryption if needed */
// 	if ((NULL != pSessionInfo) &&
// 		(0 != (pResSessionHdr->PayloadType & CONFIDENT_MASK)))
// 	{
// 		pConfHdr = (  uint8_t*)(pResSessionHdr + 1);
// 		switch (pSessionInfo->ConfidentialityAlgorithm)
// 		{
// 		case CONF_AES_CBC_128:

// 			/* Fill Init Vector */
// 			for (i =0; i < CONF_AES_CBC_128_HDR_LEN; i++)
// 			{
// 				pConfHdr [i] = (uint8_t)rand_r (&seed);
// 			}
// 			pConfPayld = pConfHdr + CONF_AES_CBC_128_HDR_LEN;

// 			/* Add Padding; include size of confpadlen */
// 			ConfPadLen = (PayloadLen + 1) % CONF_BLOCK_SIZE;
// 			if (0 != ConfPadLen)
// 			{
// 				ConfPadLen =  CONF_BLOCK_SIZE - ConfPadLen;
// 			}
// 			for (i = 0; i < ConfPadLen; i++)
// 			{
// 				*(pPayload + PayloadLen + i) = i + 1;
// 			}
// 			*(pPayload + PayloadLen + ConfPadLen) = ConfPadLen;
// 			ConfPayldLen = PayloadLen + ConfPadLen + 1;
// 			aesEncrypt ((  uint8_t*)pPayload,  ConfPayldLen,
// 						(  uint8_t*)pConfHdr, pSessionInfo->Key2,
// 						(  uint8_t*)pConfPayld);

// 			IPMI_DBG_PRINT_BUF ((  uint8_t*)pConfPayld, ConfPayldLen);
// 			PayloadLen	  = ConfPayldLen + CONF_AES_CBC_128_HDR_LEN;
// 			pBMCInfo->LANConfig.MsgReq.Size = PayloadLen;
// 			break;

// 		case CONF_xCR4_128:
// 		case CONF_xCR4_40:
// 		default:
// 			IPMI_WARNING ("RMCP.c : Invalid confidentiality Algorithm\n");
// 			return 0;
// 		}
// 	}
// 	else
// 	{
// 		_fmemcpy (pRes, pPayload, PayloadLen);
// 	}

// 	/* Fill Payload Length */
// 	pResSessionHdr->IPMIMsgLen = htoipmi_u16 (PayloadLen);

// 	ResLen = sizeof (RMCPHdr_T) + sizeof (SessionHdr2_T) + PayloadLen;

// 	/* Add Integrity Check Value */
// 	if ((NULL != pSessionInfo) &&
// 		(0 != (pResSessionHdr->PayloadType & INTEGRITY_MASK)))
// 	{
// 		/* Add Integrity Pad */
// 		pIntPad   = (  uint8_t*)(pResSessionHdr + 1) + PayloadLen;
// 		IntPadLen = (sizeof (SessionHdr2_T) + PayloadLen + 2) % sizeof (uint32_t);
// 		if (0 != IntPadLen)
// 		{
// 			IntPadLen  = sizeof(uint32_t) - IntPadLen;
// 		}
// 		_fmemset (pIntPad, 0xFF, IntPadLen);
// 		*(pIntPad + IntPadLen)      = IntPadLen;    /* Integrity Pad Len  */
// 		*(pIntPad + IntPadLen + 1)  = 0x07;         /* Next Header        */

// 		pResMsgAuthCode =  pIntPad + IntPadLen + 2;
// 		AuthCodeLen     = sizeof (SessionHdr2_T) + PayloadLen + IntPadLen + 2;
// 		ResLen          += IntPadLen + 2;

// 		switch (pSessionInfo->IntegrityAlgorithm)
// 		{
// 		case AUTH_HMAC_SHA1_96:

// 			hmac_sha1 ((uint8_t *)pSessionInfo->Key1, HASH_KEY1_SIZE,
// 					   (  uint8_t*)pResSessionHdr, AuthCodeLen,
// 					   (uint8_t *)pResMsgAuthCode, MAX_INTEGRITY_LEN);
// 			ResLen += HMAC_SHA1_96_LEN;
// 			break;

// 		case AUTH_HMAC_MD5_128:
// 			hmac_md5(pSessionInfo->Key1,HASH_KEY1_SIZE,(  uint8_t*)pResSessionHdr, AuthCodeLen,
// 			pResMsgAuthCode, MAX_HMAC_MD5_INTEGRITY_LEN);
// 			ResLen += HMAC_MD5_LEN;
// 			break;
			
// 		case AUTH_MD5_128:
// 			MD5_128((char *)pSessionInfo->Password,MAX_PASSWORD_LEN,(  INT8S*)pResSessionHdr, AuthCodeLen,
// 			(char *)pResMsgAuthCode, MAX_MD5_INTEGRITY_LEN);
// 			ResLen += MD5_LEN;
// 			break;
			
// 		case AUTH_HMAC_SHA256_128:
	
// 			hmac_sha256 ((unsigned char *)pSessionInfo->Key1, SHA2_HASH_KEY_SIZE, (unsigned char *)pResSessionHdr,
// 					AuthCodeLen, (unsigned char *)pResMsgAuthCode, HMAC_SHA256_128_LEN);                
// 			ResLen += HMAC_SHA256_128_LEN;  
// 			break;

// 		default:
// 			IPMI_WARNING ("RMCP.c : Invalid Integrity Algorithm\n");
// 			return 0;
// 		}
// 	}

// 	return ResLen;
// }

// int RMCPplusSeqNumValidation(SessionInfo_T * pSessionInfo,uint32_t SessionSeqNum)
// {
// 	uint32_t SeqTrac[SIXTEEN_COUNT_WINDOW_LEN];
// 	bool TrackRollOver = FALSE;
// 	uint32_t TrackRollOverSeq = SEQNUM_ROLLOVER;
// 	int i=0;


// 	if( pSessionInfo->InboundSeq == SessionSeqNum)
// 		return -1;

// 	if((pSessionInfo->InboundSeq < (SEQNUM_ROLLOVER -RMCPPLUS_SEQUPLIMIT)) && (pSessionInfo->InboundSeq > RMCPPLUS_SEQLOWLIMIT))
// 	{
// 		if(SessionSeqNum < pSessionInfo->InboundSeq)
// 		{
// 			if((pSessionInfo->InboundSeq -SessionSeqNum) > RMCPPLUS_SEQLOWLIMIT)
// 				return -1;
// 			else
// 			{
// 				for(i=0; i < RMCPPLUS_SEQLOWLIMIT; i++)
// 			   {
// 					if(SessionSeqNum == pSessionInfo->InboundTrac[i])
// 					{
// 						if(((1 << i) & pSessionInfo->InboundRecv) != 0)
// 							return -1;
// 						else
// 							pSessionInfo->InboundRecv |= (1<<i);
// 					}
// 				}
// 			}
// 		}
// 		else
// 		{
// 		   if((SessionSeqNum - pSessionInfo->InboundSeq) > RMCPPLUS_SEQUPLIMIT)
// 				   return -1;

// 		   _fmemcpy((uint8_t *)SeqTrac,(uint8_t *)pSessionInfo->InboundTrac,(sizeof(uint32_t) * SIXTEEN_COUNT_WINDOW_LEN));

// 			for(i=0; i < (SessionSeqNum - pSessionInfo->InboundSeq); i++)
// 						pSessionInfo->InboundTrac[i] = SessionSeqNum - (i+1);


// 			pSessionInfo->InboundRecv = pSessionInfo->InboundRecv << (SessionSeqNum - pSessionInfo->InboundSeq);
// 			pSessionInfo->InboundRecv |= (1 << ((SessionSeqNum - pSessionInfo->InboundSeq)-1));

// 			_fmemcpy((uint8_t *)&pSessionInfo->InboundTrac[SessionSeqNum - pSessionInfo->InboundSeq],
// 							   (uint8_t *)&SeqTrac[0],
// 							   (sizeof(uint32_t) *(SIXTEEN_COUNT_WINDOW_LEN - (SessionSeqNum - pSessionInfo->InboundSeq))));
// 			pSessionInfo->InboundSeq = SessionSeqNum;
// 		}
// 	}
// 	else if((pSessionInfo->InboundSeq  < RMCPPLUS_SEQLOWLIMIT)
// 			  || (pSessionInfo->InboundSeq  > (SEQNUM_ROLLOVER -RMCPPLUS_SEQUPLIMIT)))  /* Checking condition for rollover */
// 	{
// 		  if(SessionSeqNum < pSessionInfo->InboundSeq)
// 		  {
// 			  if(!((((pSessionInfo->InboundSeq -SessionSeqNum) <= RMCPPLUS_SEQLOWLIMIT) &&
// 				  (((SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1) >= RMCPPLUS_SEQLOWLIMIT )) ||
// 				  ((((SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1) <= RMCPPLUS_SEQLOWLIMIT ) &&
// 					  (pSessionInfo->InboundSeq -SessionSeqNum) >= RMCPPLUS_SEQLOWLIMIT)))
// 			   {
// 						 return -1;
// 			   }
// 			   else
// 			   {
// 					if((pSessionInfo->InboundSeq -SessionSeqNum) <= RMCPPLUS_SEQLOWLIMIT)
// 					{
// 						for(i=0; i < RMCPPLUS_SEQLOWLIMIT; i++)
// 						{
// 							if(SessionSeqNum == pSessionInfo->InboundTrac[i])
// 							{
// 								if(((1 << i) & pSessionInfo->InboundRecv) != 0)
// 									return -1;
// 								else
// 									pSessionInfo->InboundRecv |= (1<<i);
// 							}
// 						}
// 					}
// 					else if(((SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1) <= RMCPPLUS_SEQUPLIMIT )
// 					{
// 						_fmemcpy((uint8_t *)SeqTrac,(uint8_t *)pSessionInfo->InboundTrac,(sizeof(uint32_t) * SIXTEEN_COUNT_WINDOW_LEN));

// 						for(i=0; i < ((SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1) ; i++)
// 						{
// 							if(((SessionSeqNum - (i+1)) != 0) && (TrackRollOver == FALSE))
// 								pSessionInfo->InboundTrac[i] = SessionSeqNum - (i+1);
// 							else if(((SessionSeqNum - (i+1)) == 0) && (TrackRollOver == FALSE))
// 							{
// 								pSessionInfo->InboundTrac[i] = SessionSeqNum - (i+1);
// 								TrackRollOver = TRUE;
// 							}
// 							else if(TrackRollOver ==  TRUE)
// 							{
// 								pSessionInfo->InboundTrac[i] = TrackRollOverSeq;
// 								TrackRollOverSeq--;
// 							}
// 						}
// 						TrackRollOverSeq = SEQNUM_ROLLOVER;
// 						TrackRollOver = FALSE;

// 						pSessionInfo->InboundRecv = pSessionInfo->InboundRecv << ((SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1);
// 						pSessionInfo->InboundRecv |= (1 << (((SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1) -1));

// 						_fmemcpy((uint8_t *)&pSessionInfo->InboundTrac[(SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1],
// 									  (uint8_t *)&SeqTrac[0],
// 									  (sizeof(uint32_t) *(SIXTEEN_COUNT_WINDOW_LEN - ((SEQNUM_ROLLOVER - pSessionInfo->InboundSeq) + SessionSeqNum+1))));
// 						pSessionInfo->InboundSeq = SessionSeqNum;
// 					}
// 			  }
// 		  }
// 		 else if(SessionSeqNum > pSessionInfo->InboundSeq)
// 		{
// 			if(!((((SessionSeqNum -pSessionInfo->InboundSeq) <= RMCPPLUS_SEQUPLIMIT) &&
// 				(((SEQNUM_ROLLOVER - SessionSeqNum) + pSessionInfo->InboundSeq+1) >= RMCPPLUS_SEQUPLIMIT )) ||
// 				((((SEQNUM_ROLLOVER - SessionSeqNum) + pSessionInfo->InboundSeq+1) <= RMCPPLUS_SEQLOWLIMIT ) &&
// 				  (SessionSeqNum-pSessionInfo->InboundSeq) >= RMCPPLUS_SEQLOWLIMIT)))
// 			  {
// 				   return -1;
// 			  }
// 			 else
// 			 {
// 				 if((SessionSeqNum  - pSessionInfo->InboundSeq) <= RMCPPLUS_SEQUPLIMIT)
// 				 {
// 					 _fmemcpy((uint8_t *)SeqTrac,(uint8_t *)pSessionInfo->InboundTrac,(sizeof(uint32_t) * SIXTEEN_COUNT_WINDOW_LEN));
// 					  for(i=0; i < (SessionSeqNum  - pSessionInfo->InboundSeq) ; i++)
// 					  {
// 							if(((SessionSeqNum - (i+1)) != 0) && (TrackRollOver == FALSE))
// 								   pSessionInfo->InboundTrac[i] = SessionSeqNum - (i+1);
// 							else if(((SessionSeqNum - (i+1)) == 0) && (TrackRollOver == FALSE))
// 							{
// 								  pSessionInfo->InboundTrac[i] = SessionSeqNum - (i+1);
// 								  TrackRollOver = TRUE;
// 							}
// 							else if(TrackRollOver ==  TRUE)
// 							{
// 								  pSessionInfo->InboundTrac[i] = TrackRollOverSeq;
// 								  TrackRollOverSeq--;
// 							}
// 					   }
// 						TrackRollOverSeq = SEQNUM_ROLLOVER;
// 						TrackRollOver = FALSE;

// 						pSessionInfo->InboundRecv = pSessionInfo->InboundRecv << (SessionSeqNum  - pSessionInfo->InboundSeq);
// 						pSessionInfo->InboundRecv |= (1 << ((SessionSeqNum  - pSessionInfo->InboundSeq) -1));

// 						_fmemcpy((uint8_t *)&pSessionInfo->InboundTrac[SessionSeqNum  - pSessionInfo->InboundSeq],
// 									  (uint8_t *)&SeqTrac[0],
// 									  (sizeof(uint32_t) *(SIXTEEN_COUNT_WINDOW_LEN - (SessionSeqNum - pSessionInfo->InboundSeq))));
// 						pSessionInfo->InboundSeq = SessionSeqNum;
// 				 }
// 				 else if(((SEQNUM_ROLLOVER -SessionSeqNum) + pSessionInfo->InboundSeq+1) <= RMCPPLUS_SEQLOWLIMIT)
// 				 {
// 					   for(i=0; i < RMCPPLUS_SEQLOWLIMIT; i++)
// 					   {
// 							if(SessionSeqNum == pSessionInfo->InboundTrac[i])
// 						   {
// 								if(((1 << i) & pSessionInfo->InboundRecv) != 0)
// 									 return -1;
// 								else
// 									 pSessionInfo->InboundRecv |= (1<<i);
// 							}
// 					   }
// 				 }
// 			 }
// 					   }
// 	}

// 	return 0;
// }


// /**
//  * @brief Process IPMI 2.0 Payload.
//  * @param pRMCPReq - RMCP request message.
//  * @param pRMCPRes _ RMCP response message.
//  * @return 0 if success, -1 if error.
// **/
// static int
// Proc20Payload (  RMCPHdr_T* pRMCPReq,   RMCPHdr_T* pRMCPRes, MiscParams_T *pParams,uint8_t Channel )
// {
// 	  SessionHdr2_T*  pReqSession2Hdr = (  SessionHdr2_T*)(pRMCPReq + 1);
// 	  SessionHdr2_T*  pResSession2Hdr = (  SessionHdr2_T*)(pRMCPRes + 1);
// 	  uint8_t*          pReq  = (  uint8_t *)(pReqSession2Hdr + 1);
// 	  uint8_t*          pRes  = (  uint8_t *)(pResSession2Hdr + 1);
// 	   SessionInfo_T*  pSessionInfo = NULL;
// 	  uint8_t*          pIntPad;
// 	  uint8_t*          pConfHdr;
// 	  uint8_t*          pConfPayld;
// 	  uint8_t*          pReqMsgAuthCode;
// 	   UserInfo_T*     pUserInfo;
// 	   BMCInfo_t*      pBMCInfo = &g_BMCInfo[BMCInst];
// 		   uint8_t           Payload, IntPadLen, ComputedAuthCode [25];
// 		   INT16U          IPMIMsgLen, AuthCodeLen, ConfPayldLen;
// 		   uint32_t          SessionID;
// 		   uint32_t          SessionSeqNum;
// 		   int             len, i;
// 		   uint8_t           UserPswd [MAX_PASSWORD_LEN];
// 		   uint8_t PwdEncKey[MAX_SIZE_KEY + 1] = {0};

// 	/* Get SessionID & Session Seq */
// 	SessionID       = pReqSession2Hdr->SessionID;
// 	SessionSeqNum   = pReqSession2Hdr->SessionSeqNum;

// 	/* Validate IPMI Session Header */
// 	if (TRUE != ValidateSessionHdr (SessionID, SessionSeqNum, BMCInst))
// 	{
// //        IPMI_WARNING ("RMCP.c : IPMI Session header validation failed\n");
// 		return 0;
// 	}

// 	IPMIMsgLen = ipmitoh_u16 (pReqSession2Hdr->IPMIMsgLen);
// 	Payload    = pReqSession2Hdr->PayloadType & 0x3F;

// 	/* Process PreSession Payloads */
// 	for (i = 0; i < sizeof (m_PayloadTbl) / sizeof (m_PayloadTbl [0]); i++)
// 	{
// 		if (m_PayloadTbl [i].Payload == Payload)
// 		{
// 			/* Copy RMCP & Session Hdr */
// 			_fmemcpy ((  uint8_t*)pRMCPRes, (  uint8_t*)pRMCPReq,
// 					   sizeof (RMCPHdr_T) +  sizeof (SessionHdr2_T));

// 			/* For response the type is type + 1 */
// 			pResSession2Hdr->PayloadType++;
// 			/* Copy message tag from request */
// 			*pRes = *pReq;

// 			OS_THREAD_MUTEX_RELEASE(&pBMCInfo->SessionTblMutex);
// 			/* Call the function and pass the data after message tag */
// 			len = m_PayloadTbl [i].PayloadHndlr ((pReq),
// 				  (uint8_t)(IPMIMsgLen - sizeof (uint8_t)), (pRes), pParams,Channel,BMCInst);
// 			OS_THREAD_MUTEX_ACQUIRE(&pBMCInfo->SessionTblMutex,WAIT_INFINITE);

// 			/* Copy the message length */
// 			pResSession2Hdr->IPMIMsgLen = htoipmi_u16 ((len));

// 		   if(len!=0)
// 			len += sizeof (RMCPHdr_T) + sizeof (SessionHdr2_T);

// 			return len;
// 		}
// 	}

// 	/* Check for Invalid Payload Type */
// 	if ((PAYLOAD_IPMI_MSG !=  Payload) && (PAYLOAD_SOL !=  Payload))
// 	{
// 		IPMI_WARNING ("RMCP.c : Invalid payload\n");
// 		return 0;
// 	}

// 	/* check for the pre-session commands */
// 	if (0 == SessionID)
// 	{
// 		int i;
// 		  IPMIMsgHdr_T* pIPMIMsg = (  IPMIMsgHdr_T*) pReq;

// 		for (i=0; i < sizeof (m_PreSessionCmdsTbl) / sizeof (PreSessionCmd_T); i++)
// 		{
// 			if ((m_PreSessionCmdsTbl[i].NetFn == (pIPMIMsg->NetFnLUN >> 2)) &&
// 				(m_PreSessionCmdsTbl[i].Cmd == pIPMIMsg->Cmd))
// 			{
// 				pBMCInfo->LANConfig.MsgReq.Size = IPMIMsgLen;
// 				_fmemcpy (pBMCInfo->LANConfig.MsgReq.Data, pReq, pBMCInfo->LANConfig.MsgReq.Size);
// 				break;
// 			}
// 		}
// 		if (i >= (sizeof (m_PreSessionCmdsTbl) / sizeof (PreSessionCmd_T)))
// 		{
// 			IPMI_WARNING ("RMCP.c : Presession command not found\n");
// 			return 0;
// 		}
// 	}
// 	else
// 	{
// 		/* Get Session Information */
// 		pSessionInfo = getSessionInfo (SESSION_ID_INFO, &SessionID, BMCInst);

// 		if (NULL == pSessionInfo)
// 		{
// 			IPMI_WARNING ("RMCP.c : Proc20Payload - Invalid Session Id\n");
// 			return 0;
// 		}

// 		/* Check if session is activated */
// 		if (TRUE != pSessionInfo->Activated)
// 		{
// 			IPMI_WARNING ("RMCP.c : Session not activated with session id %lx\n", SessionID);
// 			return 0;
// 		}

// 		if(pBMCInfo->IpmiConfig.LinkDownResilentSupport == 1)
// 		{
// 			if(pSessionInfo->Linkstat == TRUE)
// 			{
// 				pSessionInfo->Linkstat = FALSE;
// 				memset(pSessionInfo->InboundTrac,0,SIXTEEN_COUNT_WINDOW_LEN);
// 			}
// 		}

// 		if( ((((  IPMIMsgHdr_T*)pBMCInfo->LANConfig.MsgReq.Data)->NetFnLUN)>>2==NETFN_APP) &&
// 			((((  IPMIMsgHdr_T*)pBMCInfo->LANConfig.MsgReq.Data)->Cmd)==CMD_SET_SESSION_PRIV_LEVEL) &&
// 			((pSessionInfo->EventFlag)== 1) )
// 		{
// 			 pSessionInfo->EventFlag=0;
// 			 if ( 0 != AddLoginEvent ( pSessionInfo->UserId, NULL, EVENT_LOGIN, BMCInst ))
// 			 {
// 				  TCRIT("Problem while adding Log record \n");
// 			 }
// 		}
		
// 		if(RMCPplusSeqNumValidation(pSessionInfo,ipmitoh_u32(SessionSeqNum)) != 0)
// 		{
// 			return 0;
// 		}
		
// 		if (0 != (pReqSession2Hdr->PayloadType & INTEGRITY_MASK))
// 		{
// 			uint8_t Len;

// 			/*  check Integrity pad which starts from auth type till auth code */
// 			pIntPad   = (  uint8_t*)(pReqSession2Hdr + 1) + IPMIMsgLen;

// 				IntPadLen = (sizeof (SessionHdr2_T) + IPMIMsgLen + 2) % sizeof (uint32_t);
// 			if (0 != IntPadLen)
// 			{
// 				IntPadLen  = sizeof(uint32_t) - IntPadLen;
// 			}

// 			if (pIntPad [IntPadLen] != IntPadLen)
// 			{
// 				IPMI_WARNING ("RMCP.c : Invalid Padlength\n");
// 				return 0;
// 			}

// 			/* Check auth code */
// 			pReqMsgAuthCode =  pIntPad + IntPadLen + 2;
// 			AuthCodeLen     = sizeof (SessionHdr2_T) + IPMIMsgLen + IntPadLen + 2;


// 			switch (pSessionInfo->IntegrityAlgorithm)
// 			{
// 			case AUTH_HMAC_SHA1_96:
// 				hmac_sha1 ((uint8_t *)pSessionInfo->Key1, HASH_KEY1_SIZE,
// 						   (  uint8_t*)pReqSession2Hdr, AuthCodeLen,
// 						   (  uint8_t*)ComputedAuthCode, MAX_INTEGRITY_LEN);
// 				Len = HMAC_SHA1_96_LEN;
// 				break;

// 			case AUTH_HMAC_MD5_128:
// 				hmac_md5 (pSessionInfo->Key1, HASH_KEY1_SIZE,
// 							(  uint8_t*)pReqSession2Hdr, AuthCodeLen,
// 							(  uint8_t*)ComputedAuthCode, MAX_HMAC_MD5_INTEGRITY_LEN);
// 				Len = HMAC_MD5_LEN;
// 				break;
				
// 			case AUTH_MD5_128:
// 				/* Get User Info */
// 				pUserInfo = getUserIdInfo((uint8_t)pSessionInfo->UserId, BMCInst);
// 				if (g_corefeatures.userpswd_encryption == ENABLED)
// 				{
// 					/* Get Encryption Key from the MBMCInfo_t structure */
// 						memcpy(PwdEncKey, &(g_MBMCInfo.PwdEncKey), MAX_SIZE_KEY);
// 					if(DecryptPassword((INT8S *)(pBMCInfo->EncryptedUserInfo[pSessionInfo->UserId - 1].EncryptedPswd), MAX_PASSWORD_LEN, (INT8S *)UserPswd, MAX_PASSWORD_LEN, PwdEncKey))
// 					{
// 						TCRIT("Error in decrypting the user password for user ID:%d. .\n", pSessionInfo->UserId);
// 						return -1;
// 					}
// 				}
// 				else
// 				{
// 					_fmemcpy (UserPswd, pUserInfo->UserPassword, MAX_PASSWORD_LEN);
// 				}

// 				MD5_128((char *)pUserInfo->UserPassword, MAX_PASSWORD_LEN,
// 							(  INT8S*)pReqSession2Hdr, AuthCodeLen,
// 							(  INT8S*)ComputedAuthCode, MAX_MD5_INTEGRITY_LEN);
// 				Len= MD5_LEN;
// 				break;
				
// 			case AUTH_HMAC_SHA256_128:
		
// 				hmac_sha256 ((unsigned char *)pSessionInfo->Key1, SHA2_HASH_KEY_SIZE, (unsigned char *)pReqSession2Hdr,
// 						AuthCodeLen, (unsigned char *)ComputedAuthCode, SHA2_HASH_KEY_SIZE);                
// 				Len= HMAC_SHA256_128_LEN;
// 				break;                
				
// 			default:
// 				IPMI_WARNING ("RMCP.c : Invalid Integrity Algorithm\n");
// 				return 0;
// 			}

// 			IPMI_DBG_PRINT_BUF ((  uint8_t*)ComputedAuthCode, Len);
// 			if (0 != _fmemcmp ((  uint8_t*)ComputedAuthCode, pReqMsgAuthCode, Len))
// 			{
// 				return 0;
// 			}
// 		}

// 		/*  Decrypt the message if Encrypted */
// 		/* Verify confidentiality header and trailer */
// 		if (0 != (pReqSession2Hdr->PayloadType & CONFIDENT_MASK))
// 		{
// 			pConfHdr = (  uint8_t*)(pReqSession2Hdr + 1);
// 			switch (pSessionInfo->ConfidentialityAlgorithm)
// 			{
// 			case CONF_AES_CBC_128:
// 				pConfPayld   = pConfHdr + CONF_AES_CBC_128_HDR_LEN;
// 				ConfPayldLen = IPMIMsgLen - CONF_AES_CBC_128_HDR_LEN;
// 				aesDecrypt ((  uint8_t*)pConfPayld,  ConfPayldLen,
// 							(  uint8_t*)pConfHdr, pSessionInfo->Key2,
// 							(  uint8_t*)pBMCInfo->LANConfig.MsgReq.Data);

// 				/* Remove pad length */
// 				if (pBMCInfo->LANConfig.MsgReq.Data [ConfPayldLen - 1] >  CONF_BLOCK_SIZE)
// 				{
// 					IPMI_WARNING ("Invalid Conf Blocke size  %d\n", pBMCInfo->LANConfig.MsgReq.Data [ConfPayldLen - 1]);
// 					return 0;
// 				}

// 				ConfPayldLen -= (pBMCInfo->LANConfig.MsgReq.Data [ConfPayldLen - 1] + 1);
// 				break;

// 			case CONF_xCR4_128:

// 			case CONF_xCR4_40:

// 			default:
// 				IPMI_WARNING ("RMCP.c : Invalid confidentiality Algorithm\n");
// 				return 0;
// 			}

// 			pBMCInfo->LANConfig.MsgReq.Size = ConfPayldLen;
// 		}
// 		else
// 		{
// 			pBMCInfo->LANConfig.MsgReq.Size = IPMIMsgLen;
// 			_fmemcpy (pBMCInfo->LANConfig.MsgReq.Data, pReq, pBMCInfo->LANConfig.MsgReq.Size);
// 		}
// 	}

// 	/* Fill IPMI MsgPkt Request */
// 	pBMCInfo->LANConfig.MsgReq.Cmd       = ((  IPMIMsgHdr_T*)pBMCInfo->LANConfig.MsgReq.Data)->Cmd;
// 	pBMCInfo->LANConfig.MsgReq.NetFnLUN  = ((  IPMIMsgHdr_T*)pBMCInfo->LANConfig.MsgReq.Data)->NetFnLUN;
// 	pBMCInfo->LANConfig.MsgReq.SessionID = SessionID;
// 	pBMCInfo->LANConfig.MsgReq.SessionType = LAN_SESSION_TYPE;
// 	pBMCInfo->LANConfig.MsgReq.Channel =Channel;
// 	UpdateGetMsgTime( &pBMCInfo->LANConfig.MsgReq,IfcType, BMCInst);
// 	// Moved to line 966
// 	// Bug : if SessionID is 0 this Unlock will be called without a Lock
// 	//UNLOCK_BMC_SHARED_MEM();

// 	/* Process IPMI Request */
// 	if (0 != ProcIPMIReq (pSessionInfo, Payload, pParams,Channel, BMCInst))
// 	{
// 		return 0;
// 	}

// 	/* Fill Response data */
// 	_fmemcpy (pRMCPRes, pRMCPReq, sizeof (RMCPHdr_T) + sizeof (SessionHdr_T));


// 	return Frame20Payload (pReqSession2Hdr->PayloadType, pRMCPRes,
// 						   pBMCInfo->LANConfig.MsgRes.Data, pBMCInfo->LANConfig.MsgRes.Size, pSessionInfo, BMCInst);
// }

// /**************************************************************************** 
//  * fn AddLoginEvent
//  * params:
//  * pRMCPSession  pointer to RMCP Session information
//  * EvtType	0x9 - login, 0xa - logout, 0xb - autologout, 0xc - connection lost
//  *
//  * return 	0 - success, -1 - failure
//  ***************************************************************************/
// int AddLoginEvent ( uint8_t UserID, uint8_t* UserName, uint8_t EvtType )
// {
// 	  BMCInfo_t* pBMCInfo = &g_BMCInfo[BMCInst];
	
// 	int reslen = 0, ret = -1;
// 	int i = 0;
// 	AddSELRes_T  AddSelRes;
// 	uint8_t IPAddr[IP_ADDR_LEN];
// 	SELOEM1Record_T  OEMSELRec;
	
// #ifdef  CONFIG_SPX_FEATURE_IANA_0
// 	uint8_t  MfgID[] = {  CONFIG_SPX_FEATURE_IANA_2,
// 						CONFIG_SPX_FEATURE_IANA_1, 
// 						CONFIG_SPX_FEATURE_IANA_0 };
// #else
// 	uint8_t MfgID[] = { 0, 0, 0 };
// #endif
// 	/* Hook for RMCP Login Audit */
// 	if  (g_PDKHandle[PDK_RMCPLOGINAUDIT] != NULL) 
// 	{
// 		/* Return if event type bit is not set in event mask */
// 		for (i = 0; i < sizeof(m_IPMIAuditMaskMap)/sizeof(IPMIAuditMaskTbl_T); i++)
// 		{
// 			if ((EvtType == m_IPMIAuditMaskMap[i].EventType) && 
// 				(!(pBMCInfo->LoginAuditCfg.IPMIEventMask >> m_IPMIAuditMaskMap[i].EventMask) & 0x01))
// 			{
// 				return reslen;
// 			}
// 		}

// 		ret = ((int(*)(uint8_t , uint8_t, uint8_t*, uint8_t*,int))(g_PDKHandle[PDK_RMCPLOGINAUDIT]))(EvtType, UserID, UserName, pBMCInfo->LANConfig.MsgReq.IPAddr, BMCInst);
// 		if (ret != -1)
// 		{
// 			return 0;
// 		}
	
// 		if(g_corefeatures.global_ipv6  == ENABLED)
// 		{
// 			if(IN6_IS_ADDR_V4MAPPED(pBMCInfo->LANConfig.MsgReq.IPAddr))
// 			{
// 				/* The last bytes of IP6 contains IP4 address */
// 				_fmemcpy(IPAddr, &pBMCInfo->LANConfig.MsgReq.IPAddr[IP6_ADDR_LEN - IP_ADDR_LEN], sizeof (struct in_addr));
// 			}
// 			else
// 			{
// 				/*
// 				*  IPV6 address so it will be filled with 0xff. 
// 				*/
// 				memset(IPAddr, 0xFF, sizeof (struct in_addr));
// 			}
// 		}
// 		else
// 		{
// 			_fmemcpy(IPAddr, pBMCInfo->LANConfig.MsgReq.IPAddr, sizeof (struct in_addr));
// 		}

// 		/* This structure values are AMI specific SEL Record data */
// 		OEMSELRec.ID = 0x00;
// 		OEMSELRec.Type = 0xc1;
// 		OEMSELRec.TimeStamp = 0x00;
// 		memcpy(OEMSELRec.MftrID, MfgID, sizeof(MfgID));
// 		OEMSELRec.OEMData[0] = EvtType;
// 		OEMSELRec.OEMData[1] = UserID;
// 		memcpy (&OEMSELRec.OEMData[2], IPAddr, IP_ADDR_LEN);
		
// 		OS_THREAD_MUTEX_ACQUIRE(&pBMCInfo->SELConfig.SELMutex, WAIT_INFINITE);
// 		/*we are not posting login/logout audit logs to PEF*/
// 		reslen = LockedAddSELEntry((uint8_t *)&OEMSELRec, sizeof(SELOEM1Record_T), (uint8_t *)&AddSelRes, FALSE,POST_ONLY_SEL, BMCInst);
// 		/* Enable Reservation ID which was cancelled by this event */
// 		pBMCInfo->SELConfig.RsrvIDCancelled = FALSE;
// 		OS_THREAD_MUTEX_RELEASE(&pBMCInfo->SELConfig.SELMutex);

// 		return ( (sizeof(uint8_t) == reslen) ? -1 : 0 );  //reslen is only Completion code size if error
// 	}
// 	return 0;
// }

#endif /*#if IPMI20_SUPPORT*/