/*****************************************************************
******************************************************************
***                                                            ***
***        (C)Copyright 2008, American Megatrends Inc.         ***
***                                                            ***
***                    All Rights Reserved                     ***
***                                                            ***
***       5555 Oakbrook Parkway, Norcross, GA 30093, USA       ***
***                                                            ***
***                     Phone 770.246.8600                     ***
***                                                            ***
******************************************************************
******************************************************************
******************************************************************
* 
* Filename: libipmi_usermgmt.c
*
******************************************************************/
#include "libipmi_session.h"
#include "libipmi_errorcodes.h"
#include "libipmi_usermgmt.h"
#include "com_IPMIDefs.h"
#include "com_IPMI_App.h"
#include "string.h"
#include "com_IPMI_AppDevice.h"
#include "com_IPMI_Storlead.h"


uint16_t LIBIPMI_SetUser( IPMI20_UDS_SESSION_T *pUDSSession, char *pszUsername, uint8_t byID, int timeout )
{
	SetUser_T	UserInfo;
	int			nUserNameLen;
	char		byRes[MAX_RESPONSE_SIZE];
	uint32_t		dwResLen;
	uint16_t		wRet;
	
	
	if(byID	> MAX_USER_NUM)
	{
		printf("Invalid UserID\n");
		return STATUS_CODE(0, LIBIPMI_E_INVALID_USER_ID);
	}
	else if( ((nUserNameLen=strlen(pszUsername)) == 0 ) || (nUserNameLen > MAX_USERNAME_LEN))
	{
		printf("Invalid UserName\n");
		return STATUS_CODE(0, LIBIPMI_E_INVALID_USER_NAME);
	}

	memset(&UserInfo, 0, sizeof(SetUser_T) );
	
	/* IPMI Spec Table 22-33 */
	UserInfo.byUserID = byID & ~(0xC0); 
	strcpy(UserInfo.szUserName, pszUsername);

	/* Call RAW IPMI Command */
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,
											DEFAULT_NET_FN_LUN, CMD_SET_USER_NAME,
											(uint8_t*)&UserInfo, sizeof(SetUser_T),
											byRes, &dwResLen,
											timeout);
	if(byRes[0] != 0)
	{
		printf("Delete user fail!\n");
		return -1;
	}
	
	if(wRet == LIBIPMI_E_SUCCESS)
		return STATUS_CODE(LIBIPMI_STATUS_SUCCESS, byRes[0]);
	
	return wRet;
}

uint16_t LIBIPMI_GetUser( IPMI20_UDS_SESSION_T *pUDSSession, char *pszUsername, uint8_t byID, int timeout )
{
	GetUser_T	UserInfo;
	uint32_t		dwRetLen;
	uint16_t		wRet;
	
	if(byID	>= MAX_USER_NUM)
	{
		printf("Invalid UserID\n");
		return STATUS_CODE(0, LIBIPMI_E_INVALID_USER_ID);
	}

	memset(&UserInfo, 0, sizeof(GetUser_T) );

	dwRetLen = sizeof(GetUser_T);
	byID &= ~(0xC0);
	/* Call RAW IPMI Command */
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
											DEFAULT_NET_FN_LUN, CMD_GET_USER_NAME,
											&byID, sizeof(uint8_t),
											(uint8_t *)&UserInfo, &dwRetLen,
											timeout);

	if(wRet == LIBIPMI_E_SUCCESS)
	{
		strcpy(pszUsername, UserInfo.szUserName);
		return STATUS_CODE(LIBIPMI_STATUS_SUCCESS, UserInfo.byCompletionCode);
	}
	else
	{
		pszUsername[0] = (char)0;
	}
	
	return wRet;
}

uint16_t LIBIPMI_GetAllUserInfo( IPMI20_UDS_SESSION_T *pUDSSession, UserInfo_T *userInfoTbl, int timeout )
{
	uint16_t		wRet;
	uint32_t		dwRetLen;
	uint8_t 		maxUser;
	uint8_t 		userID;
	GetUserNameRes_T		UserInfo;
	int i;

	for(i=0;i<MAX_USER_NUM;i++)
	{
		userID = i+1;
		wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
												DEFAULT_NET_FN_LUN, CMD_GET_USER_NAME,
												(uint8_t *)&userID, 1,
												(uint8_t *)&UserInfo, &dwRetLen,
												timeout);
		if((wRet != 0) || (UserInfo.CompletionCode != 0))
		{
			userInfoTbl[i].UserStatus = FALSE;
			continue;
		}

		userInfoTbl[i].UserStatus = TRUE;
		userInfoTbl[i].UserId = i+1;
		memcpy(userInfoTbl[i].UserName, UserInfo.UserName, MAX_USERNAME_LEN);		
	}
	return 0;
}

//uint8_t == bool
uint8_t LIBIPMI_AuthorVerify( IPMI20_UDS_SESSION_T *pUDSSession, char *username, char *password, int timeout )
{
	AuthorVerify_T 	req;
	uint8_t 		res;
	uint32_t		dwRetLen;
	uint16_t		wRet;	
	if((username == NULL) || (username[0] == 0))
	{
		printf("username is NULL\n");
		return FALSE;
	}

	if(strlen(username) > MAX_USERNAME_LEN)
	{
		printf("username is too long!\n");
		return FALSE;
	}

	if(strlen(password) > MAX_PASSWORD_LEN)
	{
		printf("password is too long!\n");
		return FALSE;
	}

	memset(&req, 0, sizeof(AuthorVerify_T));
	strcpy(req.name, username); 
	strcpy(req.password, password); 

	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
										NETFNLUN_IPMI_STORLEAD, CMD_AUTHOR_VERIFY,
										(uint8_t *)&req, sizeof(AuthorVerify_T),
										(uint8_t *)&res, &dwRetLen,
										timeout);
	if((wRet == 0)  && (res == 0))
	{
		//verify ok
		return TRUE;
	}

	return FALSE;
}



uint16_t LIBIPMI_SetPassword( IPMI20_UDS_SESSION_T *pUDSSession, uint8_t userid, char *password, int timeout )
{
	SetUserPswdReq_T req;
	SetUserPswdRes_T res;
	uint32_t		dwRetLen;
	uint16_t		wRet;	

	if((userid <= 0) || (userid > MAX_USER_NUM))
	{
		printf("Invalid userid: %d\n", userid);
		return -1;
	}

	if (strlen(password) > MAX_PASSWORD_LEN)
	{
		printf("Invalid password Length: %d\n", strlen(password));
		return -1;
	}

	if((password == NULL) || (password[0] == 0))
	{
		printf("password is null!\n");
		return -1;
	}

	req.UserID = userid;
	req.Operation = 0x02;
	strcpy(req.Password, password);
	printf("---> req: %s, password: %s\n", req.Password, password);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
										DEFAULT_NET_FN_LUN, CMD_SET_USER_PASSWORD,
										(uint8_t *)&req, sizeof(SetUserPswdReq_T),
										(uint8_t *)&res, &dwRetLen,
										timeout);
	if((wRet != 0)  || (res.CompletionCode != 0))
	{
		printf("Ser password fail!\n");
		return -1;
	}

	return 0;
}