/*******************************************************************
 * ********************************************************************
 * ****                                                              **
 * ****    (C)Copyright 2008-2009, American Megatrends Inc.          **
 * ****                                                              **
 * ****    All Rights Reserved.                                      **
 * ****                                                              **
 * ****    5555 , Oakbrook Pkwy, Norcross,                           **
 * ****                                                              **
 * ****    Georgia - 30093, USA. Phone-(770)-246-8600.               **
 * ****                                                              **
 * ********************************************************************
 * ********************************************************************
 * ********************************************************************
 * **
 * ** libipmi_uds_session.c
 * ** Unix Domain Socket library file
 * **
 * ** Author: Suresh V (sureshv@amiindia.co.in)
 * *******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
//#include <netinet/in.h>
//#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/file.h>
#include <fcntl.h>
#include <errno.h>
#include "libipmi_session.h"
#include "libipmi_errorcodes.h"
#include "com_IPMIDefs.h"
#include "com_IPMI_AppDevice.h"
#include "com_IPMI_IPM.h"
#include "com_IPMI_App.h"
#include <sys/syscall.h>
#define gettid()  syscall(SYS_gettid)

#define MAX_USERS 16
#define MAX_IPMI_MESSAGE_SIZE 1024   //1024


// void UDS_Close(UDS_CHANNEL_T *UDSInfo);

// uint8_t UDS_ReceiveData( UDS_CHANNEL_T *UDSInfo, char *szBuffer, uint32_t* pdwSize, int timeout);

// int UDS_SendData(UDS_CHANNEL_T *UDSInfo,char *szBuffer,uint32_t dwsize,int timeout);

// uint16_t Close_IPMI20_UDS_Session( IPMI20_SESSION_T *pSession );

// uint16_t Send_RAW_IPMI2_0_UDS_Command(IPMI20_SESSION_T *pSession,
// 										uint8_t byNetFnLUN, uint8_t byCommand,
// 										uint8_t *pszReqData, uint32_t dwReqDataLen,
// 										uint8_t *pszResData, uint32_t *pdwResDataLen,
// 										uint8_t AuthEnable,int timeout);


// int UDS_Connect(UDS_CHANNEL_T *UDSInfo,char *SocketPath);

// int GetUserNameForUserID(IPMI20_SESSION_T *pSession,uint8_t UserID,char *UserName,uint8_t AuthEnable,int timeout);

// int CheckUserPassword(IPMI20_SESSION_T *pSession, uint8_t UserID, char *Password, uint8_t AuthEnable, int timeout);

// uint32_t FillUDSMessagePacket(IPMI20_SESSION_T *pSession, uint8_t *Buffer,
//                                                         uint8_t byNetFnLUN, uint8_t byCommand,
//                                                         uint8_t *pbyReqData, uint32_t dwReqDataLen,uint8_t AuthEnable);


// int UDSGetDeviceID(IPMI20_SESSION_T *pSession,uint8_t AuthEnable,int timeout);



/*This Function is used to connect UDS Client Socket*/
int UDS_Connect(UDS_CHANNEL_T *UDSInfo,char *SocketPath)
{
    SOCKET client_sock;
    struct sockaddr_un serv_addr;

    /* Open the socket */
    client_sock = socket(AF_UNIX, SOCK_STREAM, 0);

    if(client_sock == -1)
    {
        printf("LIBIPMI_UDS_SESSION.C: Unable to create socket \n");
        return LIBIPMI_MEDIUM_E_INVALID_SOCKET;
    }

    /*Connect the client to server*/

    memset ((char *) &serv_addr, 0, sizeof (serv_addr));
    serv_addr.sun_family = AF_UNIX;
    strcpy(serv_addr.sun_path,SocketPath);

    printf("---> UDS_Connect, socket: %d, SocketPath: %s\n", client_sock, SocketPath);
    if ( connect (client_sock, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
    {
        printf("LIBIPMI_UDS_SESSION.C: Unable to connect to Server:\n");
        return LIBIPMI_MEDIUM_E_CONNECT_FAILURE;
    }

    UDSInfo->hSocket = client_sock;
    UDSInfo->byIsConnected = 1;

    return LIBIPMI_E_SUCCESS;
}






/*This Functions Fills the Packet
 * with the valid fields for UDS*/
uint32_t FillUDSMessagePacket(IPMI20_SESSION_T *pSession, uint8_t *Buffer,
                        uint8_t byNetFnLUN, uint8_t byCommand,
                        uint8_t *pbyReqData, uint32_t dwReqDataLen)
{
    uint8_t *pbyIPMIUDSData;
    IPMIUDSMsg_T *pUDSMsg;
    pUDSMsg = (IPMIUDSMsg_T *)&Buffer[0];
    pbyIPMIUDSData = &Buffer[sizeof(IPMIUDSMsg_T)];

    pUDSMsg->SessionID = pSession->hUDSSession->dwSessionID;
    pUDSMsg->ChannelNum = pSession->hUDSSession->byChannelNum;
    pUDSMsg->Privilege = pSession->hUDSSession->byRole;
 //   pUDSMsg->AuthFlag = AuthEnable;
    pUDSMsg->IPMIMsgLen = sizeof(IPMIUDSMsg_T)+dwReqDataLen+1;
    pUDSMsg->Cmd = byCommand;
    pUDSMsg->NetFnLUN = byNetFnLUN;

    memcpy(pUDSMsg->UserName, pSession->hUDSSession->szUName, MAX_USER_NAME_LEN);
    memcpy(pUDSMsg->IPAddr, pSession->hUDSSession->abyIPAddr, IP6_ADDR_LEN);
    printf("---> FillUDSMessagePacket log2\n");
    pUDSMsg->ProcessID = getpid();
    pUDSMsg->ThreadID = gettid();
    memcpy(pbyIPMIUDSData, pbyReqData, dwReqDataLen);

    return ( sizeof(IPMIUDSMsg_T) + dwReqDataLen + 1);
}

/*This Function is used to recieve
  data from UDS Interface as response*/
uint8_t UDS_ReceiveData( UDS_CHANNEL_T *UDSInfo, char *szBuffer, uint32_t* pdwSize, int timeout )
{
    struct timeval wait_time, *pwait_time;
    fd_set rdfs;
    int nDes = 0,totalrecvd = 0,ret = 0;
    IPMIUDSMsg_T *pData = (IPMIUDSMsg_T *)szBuffer;
    uint32_t nBytesRecvd = 0;

    /* Wait for the socket to get ready */
    if(timeout >= 0)
    {
        wait_time.tv_sec = timeout;
        wait_time.tv_usec = 0;
        pwait_time = &wait_time;
    }
    else
        pwait_time = NULL;

    FD_ZERO(&rdfs);
    FD_SET(UDSInfo->hSocket, &rdfs);
    nDes = UDSInfo->hSocket + 1;

    while(1)
    {
        /* wait for specified amount of time */
        ret = select (nDes, &rdfs, NULL, NULL, pwait_time);
        /* socket error */
        if(ret == SOCKET_ERROR)
        {
            if(errno == EINTR)
            {
                printf("select: %s. Continue...\n",strerror(errno));
                continue;
            }
            else
            {
                printf("select failed while waiting for read pipe \n");
                continue;
            }
        }
        else if(ret == 0)
        {
              printf("Connection timed out\n");
              return LIBIPMI_MEDIUM_E_TIMED_OUT;
         }

        /* socket is ready to receive data */
        if(FD_ISSET(UDSInfo->hSocket,&rdfs))
        {
            nBytesRecvd = recv(UDSInfo->hSocket,szBuffer+totalrecvd,MAX_RESPONSE_SIZE,0);
            if(nBytesRecvd == 0)
            {
                printf("End of File Encountered ... may be socket closure\n");
                close(UDSInfo->hSocket);
                return LIBIPMI_MEDIUM_E_RECV_DATA_FAILURE;
            }
            if(nBytesRecvd == SOCKET_ERROR)
            {
                printf("Socket Error... may be socket closure\n");
                close(UDSInfo->hSocket);
                return LIBIPMI_MEDIUM_E_RECV_DATA_FAILURE;
            }

            int i;
            printf("---> client recv %#x: ", nBytesRecvd);
            for(i=0;i<nBytesRecvd;i++)
                printf("%#x ", szBuffer[totalrecvd+i]);
            printf("\n");

            totalrecvd += nBytesRecvd;

            if(totalrecvd < sizeof(IPMIUDSMsg_T))
            {
              continue;
            }

            while(totalrecvd < pData->IPMIMsgLen)
            {
              continue;
            }
        return LIBIPMI_STATUS_SUCCESS;
       }
       close(UDSInfo->hSocket);
       return LIBIPMI_MEDIUM_E_RECV_DATA_FAILURE; 
     }
}


/*This Function is used to send the
 * data to UDS Interface*/
int UDS_SendData(UDS_CHANNEL_T *UDSInfo,char *szBuffer,uint32_t dwsize,int timeout)
{
    int nTotalBytesSent = 0, nBytesSent = 0;
    struct timeval wait_time, *pwait_time;
    fd_set wdfs;
    int ret;
    int nDes;

    /* Wait for the socket to get ready */
    if(timeout >= 0)
    {
        wait_time.tv_sec = timeout;
        wait_time.tv_usec = 0;
        pwait_time = &wait_time;
    }
    else
        pwait_time = NULL;

    FD_ZERO(&wdfs);
    FD_SET(UDSInfo->hSocket, &wdfs);
    nDes = UDSInfo->hSocket + 1;

TCPSendUDSDataSelect:
    /* wait for specified amount of time */
    ret = select (nDes, NULL, &wdfs, NULL, pwait_time);
    /* socket error */
    if(ret == SOCKET_ERROR)
    {
        if(errno == EINTR)
        {
            printf("select: %s. Continue...\n",strerror(errno));
            goto TCPSendUDSDataSelect;
        }
        else
        {
            printf("Select failed while waiting for write pipe \n");
            close(UDSInfo->hSocket);
            return LIBIPMI_MEDIUM_E_INVALID_SOCKET;
        }
    }
    /* timed out */
    else if(ret == 0)
    {
        printf("Connection timedout: Write Pipe is full \n");
        close(UDSInfo->hSocket);
        return LIBIPMI_MEDIUM_E_TIMED_OUT_ON_SEND;
    }

    if(FD_ISSET(UDSInfo->hSocket,&wdfs))
    {
        /* socket is ready to send data */
        nTotalBytesSent = 0;

        /* Till the last byte is sent */
        while( nTotalBytesSent < (int)dwsize )
        {
            /* send data */
            
            nBytesSent = send (UDSInfo->hSocket,szBuffer+nTotalBytesSent,dwsize, MSG_NOSIGNAL);
            
            int i=0;
            printf("---> client Send %#x: ",  nBytesSent);
            for (i = 0; i < nBytesSent; ++i)
            {
                printf("%#x ", szBuffer[nTotalBytesSent+i]);
            }
            printf("\n");

            /* send failure */
            if ((nBytesSent == SOCKET_ERROR) && ((EBADF == errno) || (EPIPE == errno)))
            {
                printf("Error while sending data \n");
                close(UDSInfo->hSocket);
                return LIBIPMI_MEDIUM_E_SEND_DATA_FAILURE;
            }
            else
            {
                nTotalBytesSent += nBytesSent;
                dwsize -= nTotalBytesSent;
            }
        }
        return LIBIPMI_STATUS_SUCCESS;

    }

    printf("select came out while trying to write for no good reason!!\n");
    close(UDSInfo->hSocket);
    return LIBIPMI_MEDIUM_E_SEND_DATA_FAILURE;
 }


/*This Function is used to send data
* to UDS Interface in IPMI Layer*/
uint16_t Send_RAW_IPMI2_0_UDS_Command(IPMI20_SESSION_T *pSession,
            uint8_t byNetFnLUN, uint8_t byCommand,
            uint8_t *pszReqData, uint32_t dwReqDataLen,
            uint8_t *pszResData, uint32_t *pdwResDataLen,
            int timeout)
{
   uint8_t pbyIPMIUDSMsgReq[MAX_IPMI_MESSAGE_SIZE];
   uint8_t pbyIPMIUDSResData[MAX_RESPONSE_SIZE];
   uint32_t retlen=0,byretval=0;

   memset(pbyIPMIUDSMsgReq,0,MAX_IPMI_MESSAGE_SIZE);
   memset(pbyIPMIUDSResData,0,MAX_RESPONSE_SIZE);

//   printf("---> Send_RAW_IPMI2_0_UDS_Command, log0\n");
   retlen = FillUDSMessagePacket(pSession,pbyIPMIUDSMsgReq,byNetFnLUN,byCommand,pszReqData,dwReqDataLen);

    if(retlen <= 0 )
    {
       printf("Data Length Invalid\n");
       return -1;
    }

    byretval = UDS_SendData(&pSession->hUDSSession->hUDSInfo,(char *)pbyIPMIUDSMsgReq,retlen,timeout);
    if(byretval != LIBIPMI_STATUS_SUCCESS)
        return byretval;

    byretval = UDS_ReceiveData(&pSession->hUDSSession->hUDSInfo, (char *)pbyIPMIUDSResData, pdwResDataLen,timeout);
    if(byretval == LIBIPMI_STATUS_SUCCESS)
    {
        IPMIUDSMsg_T *pIPMIUDSMsg = (IPMIUDSMsg_T *)&pbyIPMIUDSResData[0];
        uint8_t *bycompletioncode = (uint8_t *)&pbyIPMIUDSResData[sizeof(IPMIUDSMsg_T)];
        
        *pdwResDataLen = pIPMIUDSMsg->IPMIMsgLen-sizeof(IPMIUDSMsg_T) - 1;
        memcpy(pszResData,&pbyIPMIUDSResData[sizeof(IPMIUDSMsg_T)],*pdwResDataLen);
        
        if(*bycompletioncode != CC_NORMAL)
            return STATUS_CODE(IPMI_ERROR_FLAG, *bycompletioncode);
        else
        {
            if((0 == pSession->hUDSSession->dwSessionID) && (pIPMIUDSMsg->Cmd == CMD_SET_USER_PASSWORD))
            {
                pSession->hUDSSession->dwSessionID = pIPMIUDSMsg->SessionID;
                pSession->hUDSSession->byRole = pIPMIUDSMsg->Privilege;
                
                if(UDS_CHANNEL == pSession->hUDSSession->byChannelNum)
                {
                    pSession->hUDSSession->byChannelNum = pIPMIUDSMsg->ChannelNum;
                }
            }
            else if((0 == pSession->hUDSSession->dwSessionID) && (pIPMIUDSMsg->Cmd == CMD_GET_DEV_ID) )
            {
                pSession->hUDSSession->dwSessionID = pIPMIUDSMsg->SessionID;
                pSession->hUDSSession->byRole = pIPMIUDSMsg->Privilege;
                
                if(UDS_CHANNEL == pSession->hUDSSession->byChannelNum)
                {
                    pSession->hUDSSession->byChannelNum = pIPMIUDSMsg->ChannelNum;
                }
            }
        }
    }
    else
        return STATUS_CODE(IPMI_ERROR_FLAG, byretval);

    return LIBIPMI_STATUS_SUCCESS;
}







void UDS_Close(UDS_CHANNEL_T *UDSInfo )
{
    printf("---> UDS_Close\n");
    close(UDSInfo->hSocket);
    /* reset the connected flag */
    UDSInfo->byIsConnected = 0;

    return;
}

uint16_t Close_IPMI20_UDS_Session( IPMI20_SESSION_T *pSession )
{
    uint16_t	wRet;
    uint32_t	Req;
    uint8_t	byRes[MAX_RESPONSE_SIZE];
    uint32_t	dwResLen;

    printf("---> Close_IPMI20_UDS_Session\n");
   if(pSession->hUDSSession == NULL)
   {
       printf("Session Information is Null\n");
       return LIBIPMI_MEDIUM_E_INVALID_DATA;
   }

    Req = pSession->hUDSSession->dwSessionID;
    wRet =  Send_RAW_IPMI2_0_UDS_Command (pSession,DEFAULT_NET_FN_LUN,
                CMD_CLOSE_SESSION,(uint8_t *)&Req,
                sizeof (uint32_t),byRes, &dwResLen,
                pSession->hUDSSession->byDefTimeout);

    return wRet;
}


/*This Function is used to 
get the corresponding Session ID
from UDS Inteface for CIM,Smash*/
int UDSGetDeviceID(IPMI20_SESSION_T *pSession,int timeout)
{
    int RetVal = 0;
    uint32_t dwIPMIResLen;
    uint8_t pbyIPMIReq[MAX_IPMI_MESSAGE_SIZE];
    uint8_t pbyIPMIRes[MAX_RESPONSE_SIZE];
    uint32_t ReqLen;

    memset(pbyIPMIReq,0,sizeof(pbyIPMIReq));
    memset(pbyIPMIRes,0,sizeof(pbyIPMIRes));

    /* The Request Data is only 
    Command Number and NetFn
    so ReqLen is Zero here*/
    ReqLen = 0;
    //dwIPMIResLen = sizeof(GetDevIDRes_T);
    RetVal = Send_RAW_IPMI2_0_UDS_Command (pSession,DEFAULT_NET_FN_LUN,
                CMD_GET_DEV_ID,pbyIPMIReq,ReqLen,
                pbyIPMIRes, &dwIPMIResLen,timeout);
    if(RetVal == LIBIPMI_E_SUCCESS)
    {
         GetDevIDRes_T *pUDSGetDevIDRes = (GetDevIDRes_T *)&pbyIPMIRes[0];
         if(pUDSGetDevIDRes->CompletionCode == CC_NORMAL)
         {
            return CC_NORMAL;
         }
         else
            return(pUDSGetDevIDRes->CompletionCode);
    }
    else
        return RetVal;

    return LIBIPMI_E_SUCCESS;
}

/*This API is used to create the IPMI Session
for the web,CIM and Smash*/
uint16_t Create_IPMI20_UDS_Session(IPMI20_SESSION_T *pSession, char *pszSocketPath,
                             char *pszUserName, char *pszPassword, uint8_t *byPrivLevel,
                             char *pUserName, uint8_t *ipaddr, int timeout,uint8_t ChannelNum)
{
    uint8_t retval = 0;
    uint8_t UserID = 0;

    printf("---> Create_IPMI20_UDS_Session\n");

    pSession->hUDSSession = (IPMI20_UDS_SESSION_T*)malloc( sizeof(IPMI20_UDS_SESSION_T) );
    if(pSession->hUDSSession == NULL)
    {
        printf("Could not allocate Memory\n");
        return -1;
    }
    memset(pSession->hUDSSession, 0, sizeof(IPMI20_UDS_SESSION_T));

    if(strlen(pszUserName)!=0)
    {
        strcpy(pSession->hUDSSession->szUserName,pszUserName);
    }
    if(strlen(pszPassword)!=0)
    {
        strcpy(pSession->hUDSSession->szPwd,pszPassword);
    }

    if( (NULL != pUserName) && (0 != strlen(pUserName)) && (strlen(pUserName) < MAX_USER_NAME_LEN) )
    {
        strcpy(pSession->hUDSSession->szUName, pUserName);
    }
    else
    {
        strcpy(pSession->hUDSSession->szUName, "");
    }
    if(NULL != ipaddr)
    {
        memcpy(pSession->hUDSSession->abyIPAddr, ipaddr, IP6_ADDR_LEN);
    }
    else
    {
        memset(pSession->hUDSSession->abyIPAddr, 0, IP6_ADDR_LEN);
    }


    pSession->hUDSSession->byPreSession = TRUE;
    pSession->hUDSSession->dwSessionID = 0;
    pSession->hUDSSession->byRole = *byPrivLevel;
    pSession->hUDSSession->byChannelNum = ChannelNum;

    pSession->byMediumType = UDS_MEDIUM;


    retval = UDS_Connect(&pSession->hUDSSession->hUDSInfo,pszSocketPath);
    if(LIBIPMI_STATUS_SUCCESS != retval)
    {
        printf("Unable to Connect\n");
        return STATUS_CODE(MEDIUM_ERROR_FLAG, retval);
    }
    // if(AUTH_FLAG == AuthFlag)
    // {
    //     retval = LIBIPMI_GetUserIDForUserName(pSession, pszUserName, pszPassword, &UserID, AuthFlag, timeout);
    //     if(LIBIPMI_STATUS_SUCCESS == retval)
    //     {
    //         if (UserID != 0)
    //         {
    //             *byPrivLevel = pSession->hUDSSession->byRole;
    //             pSession->hUDSSession->byPreSession = 0;
    //             pSession->bySessionStarted = SESSION_STARTED;
    //             pSession->hUDSSession->byDefTimeout = timeout;
    //             return LIBIPMI_E_SUCCESS;
    //         }
    //     }
    //     else
    //         return STATUS_CODE(0, LIBIPMI_E_INVALID_USER_NAME);

    // }
    // else if(AUTH_BYPASS_FLAG == AuthFlag)
    // {
    retval = UDSGetDeviceID(pSession,timeout);
    if(retval == LIBIPMI_E_SUCCESS)
    {
        *byPrivLevel = pSession->hUDSSession->byRole;
        pSession->hUDSSession->byPreSession = 0;
        pSession->bySessionStarted = SESSION_STARTED;
        pSession->hUDSSession->byDefTimeout = timeout;
        return LIBIPMI_E_SUCCESS;
    }
    return retval;
    // }
    // else
    //     return LIBIPMI_E_AUTHTYPE_NOT_SUPPORTED;

    //return 0;
}

/**
This Function is used to get the Username for the given UserID.
UserID is IN argument, UserName is OUT argument.
**/
int GetUserNameForUserID(IPMI20_SESSION_T *pSession,uint8_t UserID,char *UserName,int timeout)
{
    uint8_t pbyIPMIReq [MAX_REQUEST_SIZE];
    uint8_t pbyIPMIRes [MAX_RESPONSE_SIZE];
    GetUserNameReq_T* pUserNameReq;
    GetUserNameRes_T* pUserNameRes;
    uint32_t reslen = 0;
    int retval = 0;

    pUserNameReq = (GetUserNameReq_T *)&pbyIPMIReq[0];
    memset(pUserNameReq,0,sizeof(GetUserNameReq_T));

    pUserNameReq->UserID = UserID;
    reslen = sizeof(GetUserNameRes_T);
    retval = Send_RAW_IPMI2_0_UDS_Command ( pSession,
                DEFAULT_NET_FN_LUN, CMD_GET_USER_NAME,
                pbyIPMIReq, sizeof (GetUserNameReq_T),
                pbyIPMIRes, &reslen,
                timeout);

    if(retval == LIBIPMI_E_SUCCESS)
    {
        pUserNameRes = (GetUserNameRes_T *)&pbyIPMIRes[0];
        if(pUserNameRes->CompletionCode == CC_NORMAL)
        {
            memcpy(UserName,pUserNameRes->UserName,strlen((char *)pUserNameRes->UserName));
            return CC_NORMAL;
        }
        else
            return (pUserNameRes->CompletionCode);
    }
    else
        return retval;

    return LIBIPMI_E_SUCCESS;
}


/**
This function is used to check the password matches with the corresponding User ID.
First it will get 20byte password, if it matches then it returns SUCCCESS.
otherwise it will try for 16byte password, if it matches then it returns SUCCESS.
UserID and Password are IN arguments.
**/
int CheckUserPassword(IPMI20_SESSION_T *pSession, uint8_t UserID, char *Password, int timeout)
{
    SetUserPswdReq_T UDSReqSetUserPsswd;
    SetUserPswdRes_T UDSResSetUserPsswd;
    uint32_t reslen = 0;
    int retval = 0;

    /*First check whether it is a 20 byte password*/
    memset(&UDSReqSetUserPsswd,0,sizeof(SetUserPswdReq_T));
    memset(&UDSResSetUserPsswd,0,sizeof(SetUserPswdRes_T));
    UDSReqSetUserPsswd.UserID = (uint8_t)(BIT7|UserID);
    UDSReqSetUserPsswd.Operation = 0x03;
    strncpy((char*)UDSReqSetUserPsswd.Password, (char *)Password, MAX_PASSWORD_LEN);

    reslen = sizeof(SetUserPswdRes_T);
    retval =  Send_RAW_IPMI2_0_UDS_Command(pSession,
                  DEFAULT_NET_FN_LUN,CMD_SET_USER_PASSWORD,
                  (uint8_t *)&UDSReqSetUserPsswd,sizeof(SetUserPswdReq_T),
                  (uint8_t *)&UDSResSetUserPsswd,&reslen,
                  timeout);

    if((retval == STATUS_CODE(IPMI_ERROR_FLAG,CC_PASSWORD_TEST_FAILED_WRONG_SIZE)) &&
       (IPMI15_MAX_PASSWORD_LEN >= strlen (Password)))
    {
        /*Password may be 16 Byte Password so trying it out*/
        memset(&UDSReqSetUserPsswd,0,sizeof(SetUserPswdReq_T));
        memset(&UDSResSetUserPsswd,0,sizeof(SetUserPswdRes_T));

        UDSReqSetUserPsswd.UserID = (uint8_t)(UserID);
        UDSReqSetUserPsswd.Operation = 0x03;
        strncpy((char *)UDSReqSetUserPsswd.Password, (char *)Password, MAX_PASSWORD_LEN);
        reslen = sizeof(SetUserPswdRes_T);

        retval = Send_RAW_IPMI2_0_UDS_Command(pSession,
                    DEFAULT_NET_FN_LUN,CMD_SET_USER_PASSWORD,
                    (uint8_t *)&UDSReqSetUserPsswd,sizeof(SetUserPswdReq_T)-4,
                    (uint8_t *)&UDSResSetUserPsswd,&reslen,
                    timeout);

        return retval;
    }
    else
        return retval;

    return 0;
}